<!DOCTYPE html>
<!-- The hangout API JavaScript. Always include this first -->
<script src="//hangoutsapi.talkgadget.google.com/hangouts/api/hangout.js?v=1.3"></script>

<!-- The JavaScript for this app. This must always be a full URL not a
     relative path.
     Tip: You can load it from a local web server such as
     http://localhost/app.js for faster single user development -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="//awesometelenp.appspot.com/static/js.v7/eventemitter2.min.js"></script>


<script type="text/javascript" src="//awesometelenp.appspot.com/static/js.v7/roslib.min.js"></script>
<script type="text/javascript"><!-- /script  -->

!function(d,b){var e=Array.isArray?Array.isArray:function h(k){return Object.prototype.toString.call(k)==="[object Array]"};var f=10;function i(){this._events={};if(this._conf){a.call(this,this._conf)}}function a(k){if(k){this._conf=k;k.delimiter&&(this.delimiter=k.delimiter);k.maxListeners&&(this._events.maxListeners=k.maxListeners);k.wildcard&&(this.wildcard=k.wildcard);k.newListener&&(this.newListener=k.newListener);if(this.wildcard){this.listenerTree={}}}}function j(k){this._events={};this.newListener=false;a.call(this,k)}function c(l,t,y,n){if(!y){return[]}var u=[],q,p,w,x,s,r,m,k=t.length,o=t[n],v=t[n+1];if(n===k&&y._listeners){if(typeof y._listeners==="function"){l&&l.push(y._listeners);return[y]}else{for(q=0,p=y._listeners.length;q<p;q++){l&&l.push(y._listeners[q])}return[y]}}if((o==="*"||o==="**")||y[o]){if(o==="*"){for(w in y){if(w!=="_listeners"&&y.hasOwnProperty(w)){u=u.concat(c(l,t,y[w],n+1))}}return u}else{if(o==="**"){m=(n+1===k||(n+2===k&&v==="*"));if(m&&y._listeners){u=u.concat(c(l,t,y,k))}for(w in y){if(w!=="_listeners"&&y.hasOwnProperty(w)){if(w==="*"||w==="**"){if(y[w]._listeners&&!m){u=u.concat(c(l,t,y[w],k))}u=u.concat(c(l,t,y[w],n))}else{if(w===v){u=u.concat(c(l,t,y[w],n+2))}else{u=u.concat(c(l,t,y[w],n))}}}}return u}}u=u.concat(c(l,t,y[o],n+1))}x=y["*"];if(x){c(l,t,x,n+1)}s=y["**"];if(s){if(n<k){if(s._listeners){c(l,t,s,k)}for(w in s){if(w!=="_listeners"&&s.hasOwnProperty(w)){if(w===v){c(l,t,s[w],n+2)}else{if(w===o){c(l,t,s[w],n+1)}else{r={};r[w]=s[w];c(l,t,{"**":r},n+1)}}}}}else{if(s._listeners){c(l,t,s,k)}else{if(s["*"]&&s["*"]._listeners){c(l,t,s["*"],k)}}}}return u}function g(q,r){q=typeof q==="string"?q.split(this.delimiter):q.slice();for(var p=0,n=q.length;p+1<n;p++){if(q[p]==="**"&&q[p+1]==="**"){return}}var l=this.listenerTree;var o=q.shift();while(o){if(!l[o]){l[o]={}}l=l[o];if(q.length===0){if(!l._listeners){l._listeners=r}else{if(typeof l._listeners==="function"){l._listeners=[l._listeners,r]}else{if(e(l._listeners)){l._listeners.push(r);if(!l._listeners.warned){var k=f;if(typeof this._events.maxListeners!=="undefined"){k=this._events.maxListeners}if(k>0&&l._listeners.length>k){l._listeners.warned=true;console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",l._listeners.length);console.trace()}}}}}return true}o=q.shift()}return true}j.prototype.delimiter=".";j.prototype.setMaxListeners=function(k){this._events||i.call(this);this._events.maxListeners=k;if(!this._conf){this._conf={}}this._conf.maxListeners=k};j.prototype.event="";j.prototype.once=function(l,k){this.many(l,1,k);return this};j.prototype.many=function(n,k,m){var l=this;if(typeof m!=="function"){throw new Error("many only accepts instances of Function")}function o(){if(--k===0){l.off(n,o)}m.apply(this,arguments)}o._origin=m;this.on(n,o);return l};j.prototype.emit=function(){this._events||i.call(this);var r=arguments[0];if(r==="newListener"&&!this.newListener){if(!this._events.newListener){return false}}if(this._all){var k=arguments.length;var m=new Array(k-1);for(var n=1;n<k;n++){m[n-1]=arguments[n]}for(n=0,k=this._all.length;n<k;n++){this.event=r;this._all[n].apply(this,m)}}if(r==="error"){if(!this._all&&!this._events.error&&!(this.wildcard&&this.listenerTree.error)){if(arguments[1] instanceof Error){throw arguments[1]}else{throw new Error("Uncaught, unspecified 'error' event.")}return false}}var q;if(this.wildcard){q=[];var p=typeof r==="string"?r.split(this.delimiter):r.slice();c.call(this,q,p,this.listenerTree,0)}else{q=this._events[r]}if(typeof q==="function"){this.event=r;if(arguments.length===1){q.call(this)}else{if(arguments.length>1){switch(arguments.length){case 2:q.call(this,arguments[1]);break;case 3:q.call(this,arguments[1],arguments[2]);break;default:var k=arguments.length;var m=new Array(k-1);for(var n=1;n<k;n++){m[n-1]=arguments[n]}q.apply(this,m)}}}return true}else{if(q){var k=arguments.length;var m=new Array(k-1);for(var n=1;n<k;n++){m[n-1]=arguments[n]}var o=q.slice();for(var n=0,k=o.length;n<k;n++){this.event=r;o[n].apply(this,m)}return(o.length>0)||this._all}else{return this._all}}};j.prototype.on=function(l,n){if(typeof l==="function"){this.onAny(l);return this}if(typeof n!=="function"){throw new Error("on only accepts instances of Function")}this._events||i.call(this);this.emit("newListener",l,n);if(this.wildcard){g.call(this,l,n);return this}if(!this._events[l]){this._events[l]=n}else{if(typeof this._events[l]==="function"){this._events[l]=[this._events[l],n]}else{if(e(this._events[l])){this._events[l].push(n);if(!this._events[l].warned){var k=f;if(typeof this._events.maxListeners!=="undefined"){k=this._events.maxListeners}if(k>0&&this._events[l].length>k){this._events[l].warned=true;console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[l].length);console.trace()}}}}}return this};j.prototype.onAny=function(k){if(!this._all){this._all=[]}if(typeof k!=="function"){throw new Error("onAny only accepts instances of Function")}this._all.push(k);return this};j.prototype.addListener=j.prototype.on;j.prototype.off=function(q,l){if(typeof l!=="function"){throw new Error("removeListener only takes instances of Function")}var m,t=[];if(this.wildcard){var r=typeof q==="string"?q.split(this.delimiter):q.slice();t=c.call(this,null,r,this.listenerTree,0)}else{if(!this._events[q]){return this}m=this._events[q];t.push({_listeners:m})}for(var s=0;s<t.length;s++){var p=t[s];m=p._listeners;if(e(m)){var o=-1;for(var n=0,k=m.length;n<k;n++){if(m[n]===l||(m[n].listener&&m[n].listener===l)||(m[n]._origin&&m[n]._origin===l)){o=n;break}}if(o<0){return this}if(this.wildcard){p._listeners.splice(o,1)}else{this._events[q].splice(o,1)}if(m.length===0){if(this.wildcard){delete p._listeners}else{delete this._events[q]}}}else{if(m===l||(m.listener&&m.listener===l)||(m._origin&&m._origin===l)){if(this.wildcard){delete p._listeners}else{delete this._events[q]}}}}return this};j.prototype.offAny=function(o){var n=0,k=0,m;if(o&&this._all&&this._all.length>0){m=this._all;for(n=0,k=m.length;n<k;n++){if(o===m[n]){m.splice(n,1);return this}}}else{this._all=[]}return this};j.prototype.removeListener=j.prototype.off;j.prototype.removeAllListeners=function(o){if(arguments.length===0){!this._events||i.call(this);return this}if(this.wildcard){var n=typeof o==="string"?o.split(this.delimiter):o.slice();var m=c.call(this,null,n,this.listenerTree,0);for(var l=0;l<m.length;l++){var k=m[l];k._listeners=null}}else{if(!this._events[o]){return this}this._events[o]=null}return this};j.prototype.listeners=function(m){if(this.wildcard){var k=[];var l=typeof m==="string"?m.split(this.delimiter):m.slice();c.call(this,k,l,this.listenerTree,0);return k}this._events||i.call(this);if(!this._events[m]){this._events[m]=[]}if(!e(this._events[m])){this._events[m]=[this._events[m]]}return this._events[m]};j.prototype.listenersAny=function(){if(this._all){return this._all}else{return[]}};if(typeof define==="function"&&define.amd){define(function(){return j})}else{d.EventEmitter2=j}}(typeof process!=="undefined"&&typeof process.title!=="undefined"&&typeof exports!=="undefined"?exports:window); 
 
var ROSLIB=ROSLIB||{REVISION:"6"};ROSLIB.URDF_SPHERE=0,ROSLIB.URDF_BOX=1,ROSLIB.URDF_CYLINDER=2,ROSLIB.URDF_MESH=3,ROSLIB.ActionClient=function(t){var e=this;t=t||{},this.ros=t.ros,this.serverName=t.serverName,this.actionName=t.actionName,this.timeout=t.timeout,this.goals={};var i=!1,s=new ROSLIB.Topic({ros:this.ros,name:this.serverName+"/feedback",messageType:this.actionName+"Feedback"}),n=new ROSLIB.Topic({ros:this.ros,name:this.serverName+"/status",messageType:"actionlib_msgs/GoalStatusArray"}),o=new ROSLIB.Topic({ros:this.ros,name:this.serverName+"/result",messageType:this.actionName+"Result"});this.goalTopic=new ROSLIB.Topic({ros:this.ros,name:this.serverName+"/goal",messageType:this.actionName+"Goal"}),this.cancelTopic=new ROSLIB.Topic({ros:this.ros,name:this.serverName+"/cancel",messageType:"actionlib_msgs/GoalID"}),this.goalTopic.advertise(),this.cancelTopic.advertise(),n.subscribe(function(t){i=!0,t.status_list.forEach(function(t){var i=e.goals[t.goal_id.id];i&&i.emit("status",t)})}),s.subscribe(function(t){var i=e.goals[t.status.goal_id.id];i&&(i.emit("status",t.status),i.emit("feedback",t.feedback))}),o.subscribe(function(t){var i=e.goals[t.status.goal_id.id];i&&(i.emit("status",t.status),i.emit("result",t.result))}),this.timeout&&setTimeout(function(){i||e.emit("timeout")},this.timeout)},ROSLIB.ActionClient.prototype.__proto__=EventEmitter2.prototype,ROSLIB.ActionClient.prototype.cancel=function(){var t=new ROSLIB.Message;this.cancelTopic.publish(t)},ROSLIB.Goal=function(t){var e=this;this.actionClient=t.actionClient,this.goalMessage=t.goalMessage,this.isFinished=!1;var i=new Date;this.goalID="goal_"+Math.random()+"_"+i.getTime(),this.goalMessage=new ROSLIB.Message({goal_id:{stamp:{secs:0,nsecs:0},id:this.goalID},goal:this.goalMessage}),this.on("status",function(t){e.status=t}),this.on("result",function(t){e.isFinished=!0,e.result=t}),this.on("feedback",function(t){e.feedback=t}),this.actionClient.goals[this.goalID]=this},ROSLIB.Goal.prototype.__proto__=EventEmitter2.prototype,ROSLIB.Goal.prototype.send=function(t){var e=this;e.actionClient.goalTopic.publish(e.goalMessage),t&&setTimeout(function(){e.isFinished||e.emit("timeout")},t)},ROSLIB.Goal.prototype.cancel=function(){var t=new ROSLIB.Message({id:this.goalID});this.actionClient.cancelTopic.publish(t)},ROSLIB.Message=function(t){var e=this;t=t||{},Object.keys(t).forEach(function(i){e[i]=t[i]})},ROSLIB.Param=function(t){t=t||{},this.ros=t.ros,this.name=t.name},ROSLIB.Param.prototype.get=function(t){var e=new ROSLIB.Service({ros:this.ros,name:"/rosapi/get_param",serviceType:"rosapi/GetParam"}),i=new ROSLIB.ServiceRequest({name:this.name,value:JSON.stringify("")});e.callService(i,function(e){var i=JSON.parse(e.value);t(i)})},ROSLIB.Param.prototype.set=function(t){var e=new ROSLIB.Service({ros:this.ros,name:"/rosapi/set_param",serviceType:"rosapi/SetParam"}),i=new ROSLIB.ServiceRequest({name:this.name,value:JSON.stringify(t)});e.callService(i,function(){})},ROSLIB.Ros=function(t){t=t||{};var e=t.url;this.socket=null,this.idCounter=0,this.setMaxListeners(0),e&&this.connect(e)},ROSLIB.Ros.prototype.__proto__=EventEmitter2.prototype,ROSLIB.Ros.prototype.connect=function(t){function e(t){a.emit("connection",t)}function i(t){a.emit("close",t)}function s(t){a.emit("error",t)}function n(t,e){var i=new Image;i.onload=function(){var t=document.createElement("canvas"),s=t.getContext("2d");t.width=i.width,t.height=i.height,s.drawImage(i,0,0);for(var n=s.getImageData(0,0,i.width,i.height).data,o="",a=0;n.length>a;a+=4)o+=String.fromCharCode(n[a],n[a+1],n[a+2]);var r=JSON.parse(o);e(r)},i.src="data:image/png;base64,"+t.data}function o(t){function e(t){"publish"===t.op?a.emit(t.topic,t.msg):"service_response"===t.op&&a.emit(t.id,t.values)}var i=JSON.parse(t.data);"png"===i.op?n(i,function(t){e(t)}):e(i)}var a=this;this.socket=new WebSocket(t),this.socket.onopen=e,this.socket.onclose=i,this.socket.onerror=s,this.socket.onmessage=o},ROSLIB.Ros.prototype.close=function(){this.socket&&this.socket.close()},ROSLIB.Ros.prototype.authenticate=function(t,e,i,s,n,o,a){var r={op:"auth",mac:t,client:e,dest:i,rand:s,t:n,level:o,end:a};this.callOnConnection(r)},ROSLIB.Ros.prototype.callOnConnection=function(t){var e=this,i=JSON.stringify(t);this.socket&&this.socket.readyState===WebSocket.OPEN?e.socket.send(i):e.once("connection",function(){e.socket.send(i)})},ROSLIB.Ros.prototype.getTopics=function(t){var e=new ROSLIB.Service({ros:this,name:"/rosapi/topics",serviceType:"rosapi/Topics"}),i=new ROSLIB.ServiceRequest;e.callService(i,function(e){t(e.topics)})},ROSLIB.Ros.prototype.getServices=function(t){var e=new ROSLIB.Service({ros:this,name:"/rosapi/services",serviceType:"rosapi/Services"}),i=new ROSLIB.ServiceRequest;e.callService(i,function(e){t(e.services)})},ROSLIB.Ros.prototype.getParams=function(t){var e=new ROSLIB.Service({ros:this,name:"/rosapi/get_param_names",serviceType:"rosapi/GetParamNames"}),i=new ROSLIB.ServiceRequest;e.callService(i,function(e){t(e.names)})},ROSLIB.Service=function(t){t=t||{},this.ros=t.ros,this.name=t.name,this.serviceType=t.serviceType},ROSLIB.Service.prototype.callService=function(t,e){this.ros.idCounter++;var i="call_service:"+this.name+":"+this.ros.idCounter;this.ros.once(i,function(t){var i=new ROSLIB.ServiceResponse(t);e(i)});var s=[];Object.keys(t).forEach(function(e){s.push(t[e])});var n={op:"call_service",id:i,service:this.name,args:s};this.ros.callOnConnection(n)},ROSLIB.ServiceRequest=function(t){var e=this;t=t||{},Object.keys(t).forEach(function(i){e[i]=t[i]})},ROSLIB.ServiceResponse=function(t){var e=this;t=t||{},Object.keys(t).forEach(function(i){e[i]=t[i]})},ROSLIB.Topic=function(t){t=t||{},this.ros=t.ros,this.name=t.name,this.messageType=t.messageType,this.isAdvertised=!1,this.compression=t.compression||"none",this.throttle_rate=t.throttle_rate||0,this.compression&&"png"!==this.compression&&"none"!==this.compression&&this.emit("warning",this.compression+" compression is not supported. No compression will be used."),0>this.throttle_rate&&(this.emit("warning",this.throttle_rate+" is not allowed. Set to 0"),this.throttle_rate=0)},ROSLIB.Topic.prototype.__proto__=EventEmitter2.prototype,ROSLIB.Topic.prototype.subscribe=function(t){var e=this;this.on("message",function(e){t(e)}),this.ros.on(this.name,function(t){var i=new ROSLIB.Message(t);e.emit("message",i)}),this.ros.idCounter++;var i="subscribe:"+this.name+":"+this.ros.idCounter,s={op:"subscribe",id:i,type:this.messageType,topic:this.name,compression:this.compression,throttle_rate:this.throttle_rate};this.ros.callOnConnection(s)},ROSLIB.Topic.prototype.unsubscribe=function(){this.ros.removeAllListeners([this.name]),this.ros.idCounter++;var t="unsubscribe:"+this.name+":"+this.ros.idCounter,e={op:"unsubscribe",id:t,topic:this.name};this.ros.callOnConnection(e)},ROSLIB.Topic.prototype.advertise=function(){this.ros.idCounter++;var t="advertise:"+this.name+":"+this.ros.idCounter,e={op:"advertise",id:t,type:this.messageType,topic:this.name};this.ros.callOnConnection(e),this.isAdvertised=!0},ROSLIB.Topic.prototype.unadvertise=function(){this.ros.idCounter++;var t="unadvertise:"+this.name+":"+this.ros.idCounter,e={op:"unadvertise",id:t,topic:this.name};this.ros.callOnConnection(e),this.isAdvertised=!1},ROSLIB.Topic.prototype.publish=function(t){this.isAdvertised||this.advertise(),this.ros.idCounter++;var e="publish:"+this.name+":"+this.ros.idCounter,i={op:"publish",id:e,topic:this.name,msg:t};this.ros.callOnConnection(i)},ROSLIB.Pose=function(t){t=t||{},this.position=new ROSLIB.Vector3(t.position),this.orientation=new ROSLIB.Quaternion(t.orientation)},ROSLIB.Pose.prototype.applyTransform=function(t){this.position.multiplyQuaternion(t.rotation),this.position.add(t.translation);var e=t.rotation.clone();e.multiply(this.orientation),this.orientation=e},ROSLIB.Pose.prototype.clone=function(){return new ROSLIB.Pose(this)},ROSLIB.Quaternion=function(t){t=t||{},this.x=t.x||0,this.y=t.y||0,this.z=t.z||0,this.w=t.w||1},ROSLIB.Quaternion.prototype.conjugate=function(){this.x*=-1,this.y*=-1,this.z*=-1},ROSLIB.Quaternion.prototype.normalize=function(){var t=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===t?(this.x=0,this.y=0,this.z=0,this.w=1):(t=1/t,this.x=this.x*t,this.y=this.y*t,this.z=this.z*t,this.w=this.w*t)},ROSLIB.Quaternion.prototype.invert=function(){this.conjugate(),this.normalize()},ROSLIB.Quaternion.prototype.multiply=function(t){var e=this.x*t.w+this.y*t.z-this.z*t.y+this.w*t.x,i=-this.x*t.z+this.y*t.w+this.z*t.x+this.w*t.y,s=this.x*t.y-this.y*t.x+this.z*t.w+this.w*t.z,n=-this.x*t.x-this.y*t.y-this.z*t.z+this.w*t.w;this.x=e,this.y=i,this.z=s,this.w=n},ROSLIB.Quaternion.prototype.clone=function(){return new ROSLIB.Quaternion(this)},ROSLIB.Transform=function(t){t=t||{},this.translation=new ROSLIB.Vector3(t.translation),this.rotation=new ROSLIB.Quaternion(t.rotation)},ROSLIB.Transform.prototype.clone=function(){return new ROSLIB.Transform(this)},ROSLIB.Vector3=function(t){t=t||{},this.x=t.x||0,this.y=t.y||0,this.z=t.z||0},ROSLIB.Vector3.prototype.add=function(t){this.x+=t.x,this.y+=t.y,this.z+=t.z},ROSLIB.Vector3.prototype.subtract=function(t){this.x-=t.x,this.y-=t.y,this.z-=t.z},ROSLIB.Vector3.prototype.multiplyQuaternion=function(t){var e=t.w*this.x+t.y*this.z-t.z*this.y,i=t.w*this.y+t.z*this.x-t.x*this.z,s=t.w*this.z+t.x*this.y-t.y*this.x,n=-t.x*this.x-t.y*this.y-t.z*this.z;this.x=e*t.w+n*-t.x+i*-t.z-s*-t.y,this.y=i*t.w+n*-t.y+s*-t.x-e*-t.z,this.z=s*t.w+n*-t.z+e*-t.y-i*-t.x},ROSLIB.Vector3.prototype.clone=function(){return new ROSLIB.Vector3(this)},ROSLIB.TFClient=function(t){t=t||{},this.ros=t.ros,this.fixedFrame=t.fixedFrame||"/base_link",this.angularThres=t.angularThres||2,this.transThres=t.transThres||.01,this.rate=t.rate||10,this.goalUpdateDelay=t.goalUpdateDelay||50,this.currentGoal=!1,this.frameInfos={},this.goalUpdateRequested=!1,this.actionClient=new ROSLIB.ActionClient({ros:this.ros,serverName:"/tf2_web_republisher",actionName:"tf2_web_republisher/TFSubscriptionAction"})},ROSLIB.TFClient.prototype.processFeedback=function(t){var e=this;t.transforms.forEach(function(t){var i=t.child_frame_id,s=e.frameInfos[i];void 0!==s&&(s.transform=new ROSLIB.Transform({translation:t.transform.translation,rotation:t.transform.rotation}),s.cbs.forEach(function(t){t(s.transform)}))})},ROSLIB.TFClient.prototype.updateGoal=function(){this.currentGoal&&this.currentGoal.cancel();var t={source_frames:[],target_frame:this.fixedFrame,angular_thres:this.angularThres,trans_thres:this.transThres,rate:this.rate};for(var e in this.frameInfos)t.source_frames.push(e);this.currentGoal=new ROSLIB.Goal({actionClient:this.actionClient,goalMessage:t}),this.currentGoal.on("feedback",this.processFeedback.bind(this)),this.currentGoal.send(),this.goalUpdateRequested=!1},ROSLIB.TFClient.prototype.subscribe=function(t,e){"/"===t[0]&&(t=t.substring(1)),void 0===this.frameInfos[t]?(this.frameInfos[t]={cbs:[]},this.goalUpdateRequested||(setTimeout(this.updateGoal.bind(this),this.goalUpdateDelay),this.goalUpdateRequested=!0)):void 0!==this.frameInfos[t].transform&&e(this.frameInfos[t].transform),this.frameInfos[t].cbs.push(e)},ROSLIB.TFClient.prototype.unsubscribe=function(t,e){var i=this.frameInfos[t];if(void 0!==i){var s=i.cbs.indexOf(e);s>=0&&(i.cbs.splice(s,1),0===i.cbs.length&&delete this.frameInfos[t],this.needUpdate=!0)}},ROSLIB.UrdfBox=function(t){t=t||{};var e=this,i=t.xml;this.dimension=null,this.type=null;var s=function(t){this.type=ROSLIB.URDF_BOX;var i=t.getAttribute("size").split(" ");e.dimension=new ROSLIB.Vector3({x:parseFloat(i[0]),y:parseFloat(i[1]),z:parseFloat(i[2])})};s(i)},ROSLIB.UrdfColor=function(t){t=t||{};var e=this,i=t.xml;this.r=null,this.g=null,this.b=null,this.a=null;var s=function(t){var i=t.getAttribute("rgba").split(" ");return e.r=parseFloat(i[0]),e.g=parseFloat(i[1]),e.b=parseFloat(i[2]),e.a=parseFloat(i[3]),!0};s(i)},ROSLIB.UrdfCylinder=function(t){t=t||{};var e=this,i=t.xml;this.type=null,this.length=null,this.radius=null;var s=function(t){e.type=ROSLIB.URDF_CYLINDER,e.length=parseFloat(t.getAttribute("length")),e.radius=parseFloat(t.getAttribute("radius"))};s(i)},ROSLIB.UrdfLink=function(t){t=t||{};var e=this,i=t.xml;this.name=null,this.visual=null;var s=function(t){e.name=t.getAttribute("name");var i=t.getElementsByTagName("visual");i.length>0&&(e.visual=new ROSLIB.UrdfVisual({xml:i[0]}))};s(i)},ROSLIB.UrdfMaterial=function(t){t=t||{};var e=this,i=t.xml;this.name=null,this.textureFilename=null,this.color=null;var s=function(t){e.name=t.getAttribute("name");var i=t.getElementsByTagName("texture");i.length>0&&(e.textureFilename=i[0].getAttribute("filename"));var s=t.getElementsByTagName("color");s.length>0&&(e.color=new ROSLIB.UrdfColor({xml:s[0]}))};s(i)},ROSLIB.UrdfMesh=function(t){t=t||{};var e=this,i=t.xml;this.filename=null,this.scale=null,this.type=null;var s=function(t){e.type=ROSLIB.URDF_MESH,e.filename=t.getAttribute("filename");var i=t.getAttribute("scale");if(i){var s=i.split(" ");e.scale=new ROSLIB.Vector3({x:parseFloat(s[0]),y:parseFloat(s[1]),z:parseFloat(s[2])})}};s(i)},ROSLIB.UrdfModel=function(t){t=t||{};var e=this,i=t.xml,s=t.string;this.materials=[],this.links=[];var n=function(t){var i=t.evaluate("//robot",t,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;e.name=i.getAttribute("name");for(var s in i.childNodes){var n=i.childNodes[s];if("material"===n.tagName){var o=new ROSLIB.UrdfMaterial({xml:n});e.materials[o.name]?console.warn("Material "+o.name+"is not unique."):e.materials[o.name]=o}else if("link"===n.tagName){var a=new ROSLIB.UrdfLink({xml:n});e.links[a.name]?console.warn("Link "+a.name+" is not unique."):(a.visual&&a.visual.material&&(e.materials[a.visual.material.name]?a.visual.material=e.materials[a.visual.material.name]:a.visual.material&&(e.materials[a.visual.material.name]=a.visual.material)),e.links[a.name]=a)}}};if(s){var o=new DOMParser;i=o.parseFromString(s,"text/xml")}n(i)},ROSLIB.UrdfSphere=function(t){t=t||{};var e=this,i=t.xml;this.radius=null,this.type=null;var s=function(t){e.type=ROSLIB.URDF_SPHERE,e.radius=parseFloat(t.getAttribute("radius"))};s(i)},ROSLIB.UrdfVisual=function(t){t=t||{};var e=this,i=t.xml;this.origin=null,this.geometry=null,this.material=null;var s=function(t){var i=t.getElementsByTagName("origin");if(0===i.length)e.origin=new ROSLIB.Pose;else{var s=i[0].getAttribute("xyz"),n=new ROSLIB.Vector3;s&&(s=s.split(" "),n=new ROSLIB.Vector3({x:parseFloat(s[0]),y:parseFloat(s[1]),z:parseFloat(s[2])}));var o=i[0].getAttribute("rpy"),a=new ROSLIB.Quaternion;if(o){o=o.split(" ");var r=parseFloat(o[0]),h=parseFloat(o[1]),c=parseFloat(o[2]),l=r/2,u=h/2,p=c/2,m=Math.sin(l)*Math.cos(u)*Math.cos(p)-Math.cos(l)*Math.sin(u)*Math.sin(p),f=Math.cos(l)*Math.sin(u)*Math.cos(p)+Math.sin(l)*Math.cos(u)*Math.sin(p),v=Math.cos(l)*Math.cos(u)*Math.sin(p)-Math.sin(l)*Math.sin(u)*Math.cos(p),S=Math.cos(l)*Math.cos(u)*Math.cos(p)+Math.sin(l)*Math.sin(u)*Math.sin(p);a=new ROSLIB.Quaternion({x:m,y:f,z:v,w:S}),a.normalize()}e.origin=new ROSLIB.Pose({position:n,orientation:a})}var R=t.getElementsByTagName("geometry");if(R.length>0){var d=null;for(var g in R[0].childNodes){var O=R[0].childNodes[g];if(1===O.nodeType){d=O;break}}var y=d.nodeName;"sphere"===y?e.geometry=new ROSLIB.UrdfSphere({xml:d}):"box"===y?e.geometry=new ROSLIB.UrdfBox({xml:d}):"cylinder"===y?e.geometry=new ROSLIB.UrdfCylinder({xml:d}):"mesh"===y?e.geometry=new ROSLIB.UrdfMesh({xml:d}):console.warn("Unknown geometry type "+y)}var I=t.getElementsByTagName("material");I.length>0&&(e.material=new ROSLIB.UrdfMaterial({xml:I[0]}))};s(i)};
/*

*/
var app_manager_prefix = "/app_manager/application";

var gapi_loaded = false; // change to false for net-free test.
var mod_base = 512;
var basename = "telenp";
var test_config = false;
var tx_number = 0;
var tx_operation = "";
var tx_gapi_key = "telenp"; // used by transmitting (user) node
var tx_gapi_error = "telenp_error"; // used by turtlebot node
var tx_gapi_controller_name = "telenp_controller";
var tx_gapi_turtlebot_name = "telenp_turtlebot";
var tx_gapi_list = "telenp_list";
var rx_data = "";
var rx_error = "";
var rx_error_obj = null;
var rx_obj = null;
var rx_data_old = "";
var rx_error_old = "";
var control_retransmit = false;
var control_msgtype = 0;
var control_msgtype_rx = 0;
var control_stream = false;
var control_stream_rx = false;
var control_obstructed = false;
var control_obstructed_string = "";
var control_obstructed_num = 0;
var control_connected_motors = false;
var control_connected_rx = false;
var control_stopped = false;
var control_stopped_rx = false;
var connection = new Object();
var cmdVel = new Object();

var stream_num = 0;
var timer_key = 0;
var timer_up = 0;
var timer_down = 0;
var timer_left = 0;
var timer_right = 0;

var last_key = "stop";
var last_counter = 1;
var speed_max = 3;
var seq_ros = 0;

var MSG_STRING = 1;
var MSG_TWIST = 2;
var MSG_RESERVED = 3;

var ros;
var cmdVel;
var cmdVel2;
var cmdVel3;
var kinect_listener;

var choose_output_string = "for ROS String ouput...<br><br>" +
            "TURTLEBOT SETUP: <br>" +
			"in separate turtlebot terminals...<br>" +
			" (this is for the 'rostopic echo' method.)<br><br>" + 
			"<i style='color:blue;font-size:10pt;font-family:courier'>" +
			"$ roslaunch rosbridge_server rosbridge_websocket.launch <br>" +
			"$ rostopic echo /talker <br><br>" +
			"</i>... then look at terminal for output when" +
			" arrow buttons are clicked";
var choose_output_twist = "for ROS Twist output... <br><br>" +
            "TURTLEBOT SETUP: <br>" +
			"(on the turtlebot) " +
			"after installing tele-np ros packages execute...<br><br>" +
			"<i style='color:blue;font-size:10pt;font-family:courier'>" +
			"$ roslaunch tele_presence app_manager.launch <br><br>" +
			//"$ roslaunch turtlebot_bringup minimal.launch <br><br>" +
			"</i>... then restart this Hangout on both computers and direct " +
			"the turtlebot from the Google Hangout screen.";
var choose_output_reserved = "this option is RESERVED for future development. <br><br>" +
            "TURTLEBOT SETUP: <br>" +
			"after installing tele-np ros packages...<br><br>" +
			"<i style='color:blue;font-size:10pt;font-family:courier'>" +
			"$ roslaunch tele_presence app_manager.launch <br><br>" +
			"</i>... then direct the turtlebot from the Google Hangout screen.";
var choose_click =      "click the arrows to direct the turtlebot.";
var choose_stream = "for communication with ROS, <br>" +
            "\"Stream Mode\" clicked <br><br>" +    
            "Click to disable - on the turtlebot computer - precautions that prevent " +
			"more than one remote computer from giving instructions at the same time.";
var choose_turtlebot = "for communication with ROS, <br>" +
            "\"Turtlebot Node\" clicked <br><br>" + 
            "Click this option to tell the " +
			"system that this is the node that <i><u>this</u></i> is the node that hosts the " +
			 " actual turtlebot hardware.";
var button_center_start = '<img ' + //'src="bitmap/button_center.png"' +
			' src="//awesometelenp.appspot.com/static/bitmap/button_center.png"' +  
			' onmousedown="tryStopClick()" alt="CLICK" >';
var button_center_error = '<img ' + //'src="bitmap/button_err.png"' + 
			' src="//awesometelenp.appspot.com/static/bitmap/button_err.png"' +  
			' onmousedown="tryStopClick()" alt="ERROR" >';
var button_center_src_start = "//awesometelenp.appspot.com/static/bitmap/button_center.png";
var button_center_src_error = "//awesometelenp.appspot.com/static/bitmap/button_err.png";
var button_test_start = "static/bitmap/button_center.png";
var button_test_error = "bitmap/button_err.png";

var tab_controls_src_selected = "//awesometelenp.appspot.com/static/bitmap/tab_controls.png";
var tab_controls_src_unselected = "//awesometelenp.appspot.com/static/bitmap/tab_controls_unselected.png";
var tab_text_src_selected = "//awesometelenp.appspot.com/static/bitmap/tab_setup.png";
var tab_text_src_unselected = "//awesometelenp.appspot.com/static/bitmap/tab_setup_unselected.png";
var tab_map_src_selected = "//awesometelenp.appspot.com/static/bitmap/tab_map.png";
var tab_map_src_unselected = "//awesometelenp.appspot.com/static/bitmap/tab_map_unselected.png";


function tryLeftClick() {
	formJSONClick("left");
	if (!control_retransmit) changeHintText(choose_click); 
	if (timer_left == 0) timer_left = setInterval('formJSONClick("left")', 500);
}

function tryRightClick() {
	formJSONClick("right");
	if (!control_retransmit) changeHintText(choose_click); 
	if (timer_right == 0) timer_right = setInterval('formJSONClick("right")', 500);
}

function tryUpClick() {
	formJSONClick("up");
	if (!control_retransmit) changeHintText(choose_click); 
	if (timer_up == 0) timer_up = setInterval('formJSONClick("up")', 500);
}

function tryDownClick() {
	formJSONClick("down");
	if (!control_retransmit) changeHintText(choose_click); 
	if (timer_down == 0) timer_down = setInterval('formJSONClick("down")', 500);
}

function tryStopClick() {
	tx_number = - 1;
	stream_num = 0;
	formJSONClick("stop");
	control_stopped = false;
	control_stopped_rx = false;
	changeAlertText();
	if (!control_retransmit) changeHintText(choose_click);
	changeButtonSrc(button_center_src_start); 
	formJSONError();
}

function tryClearTimer() {
	if (timer_up != 0) {
		clearInterval(timer_up);
		timer_up = 0;
	}
	if (timer_down != 0) {
		clearInterval(timer_down);
		timer_down = 0;
	}
	if (timer_left != 0) {
		clearInterval(timer_left);
		left_left = 0;
	}
	if (timer_right != 0) {
		clearInterval(timer_right);
		timer_right = 0;
	}
}

function tryTurtlebotClick() {
	
	if (document.getElementById("setTurtlebot").checked && !control_connected_motors &&
	        isUnsetName(tx_gapi_turtlebot_name) ) { 
	    formJSONTurtlebotName();
		control_retransmit = true;
		control_msgtype = 2;
		control_connected_motors = true;
		control_connected_rx = true;
		changeHintText(choose_turtlebot);
		changeAlertText();
		document.getElementById("messageTwist").checked = true;
		trySetupROS();
		formJSONError();
		tryStreamClick();// late addition
		//document.getElementById("setStream").checked = true;// late addition
	}
	else if (control_connected_motors && isMatchingName(tx_gapi_turtlebot_name) ) {
	    gapi.hangout.data.clearValue(tx_gapi_turtlebot_name);
		//document.getElementById("setStream").checked = false;
		control_connected_motors = false;
		control_connected_rx = false;
		if (control_retransmit) formJSONError();
		control_retransmit = false;
		changeAlertText();
	}
	;//console.log(control_retransmit + "  retransmit");
}

function tryControllerClick() {
    if (document.getElementById("setController").checked && 
            isUnsetName(tx_gapi_controller_name)) {
        formJSONControllerName();
        ;//console.log("set controller");
    }
    else if ( ! isUnsetName(tx_gapi_controller_name)) {
        gapi.hangout.data.clearValue(tx_gapi_controller_name);
        ;//console.log("unset controller");
    }
}

function tryStreamClick() {
    //THIS OPTION NO LONGER EXISTS IN HTML!!
	if (control_retransmit) {
		changeHintText(choose_output_twist);
		
		if ( true) {//! document.getElementById("setStream").checked) {
			control_stream = false;
			//tx_number = -1;
		}
		else { 
			control_stream = true;
		}
		formJSONError();
	}
	else {
		//document.getElementById("setStream").checked = false;
	}
	
}

function tryRadioClick() {

	if (document.getElementById("messageString").checked) control_msgtype = MSG_STRING;

	if (document.getElementById("messageTwist").checked) control_msgtype = MSG_TWIST;	

	if (document.getElementById("messageStamped").checked) control_msgtype = MSG_RESERVED;	

	//;//console.log(control_msgtype);
	
	switch (control_msgtype) {
		case MSG_STRING:
		
			changeHintText(choose_output_string);
		break;
		
		case MSG_TWIST:
		
			changeHintText(choose_output_twist);
		break;
		
		case MSG_RESERVED:
		
			changeHintText(choose_output_reserved);
		break;
	}
}

function trySetupROS() {
    
    
    setServices();
    setKinectListener();
    setMapServices();
    inviteAndInit();
}

function setServices() {
    
    ros = new ROSLIB.Ros({
    	url : 'ws://localhost:9090'
  	});
	
	cmdVel = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/talker',
   		 messageType : 'std_msgs/String'
  	});
			
	cmdVel2 = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : 
    	    app_manager_prefix + 
    	    //'/cmd_vel_mux/input/teleop',
    	    '/mobile_base/commands/velocity',
   		 messageType : 'geometry_msgs/Twist'
  	});

    cmdVel3 = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/'+ basename +'/command_velocity',
   		 messageType : 'geometry_msgs/TwistStamped'
  	});

    kinect_listener = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : '/'+ basename +'/kinect_feedback',
   		 messageType : 'std_msgs/UInt8'
   		 
  	});
}

function trySetupControls() {
    document.getElementById("setupControls").style.display="block";
    document.getElementById("setupText").style.display="none";
    document.getElementById("setupMap").style.display="none";
    document.getElementById("alertText").style.display="block";
    
    document.getElementById("tabControls").src= tab_controls_src_selected;
    document.getElementById("tabText").src= tab_text_src_unselected;
    document.getElementById("tabMap").src= tab_map_src_unselected;
}

function trySetupText() {
    document.getElementById("setupControls").style.display="none";
    document.getElementById("setupText").style.display="block";
    document.getElementById("setupMap").style.display="none";
    document.getElementById("alertText").style.display="none";
    
    document.getElementById("tabControls").src= tab_controls_src_unselected;
    document.getElementById("tabText").src= tab_text_src_selected;
    document.getElementById("tabMap").src= tab_map_src_unselected;
}

function trySetupMap() {
    document.getElementById("setupControls").style.display="none";
    document.getElementById("setupText").style.display="none";
    document.getElementById("setupMap").style.display="block";
    document.getElementById("alertText").style.display="none";
    
    document.getElementById("tabControls").src= tab_controls_src_unselected;
    document.getElementById("tabText").src= tab_text_src_unselected;
    document.getElementById("tabMap").src= tab_map_src_selected;
}

function tryHidePadControls() {
    if (test_config) return;
    document.getElementById("padTable").style.display="none";
    //document.getElementById("turtlebotTable").style.display="block";
    document.getElementById("alertText").style.display="none";
}

function tryShowPadControls() {
    if (test_config) return;
    document.getElementById("padTable").style.display="block";
    //document.getElementById("turtlebotTable").style.display="block";
    document.getElementById("alertText").style.display="block";
}

function tryHidePadSelectControls() {
    if (test_config) return;
    document.getElementById("controllerText").style.display="none";
    
}

function tryShowPadSelectControls() {
    //if (test_config) return;
    document.getElementById("controllerText").style.display="block";
    
}

function tryHideMotorControls() {
    if (test_config) return;
    document.getElementById("turtlebotTable").style.display="none";
    document.getElementById("alertText").style.display="block";
}

function tryShowMotorControls() {
    if (test_config) return;
    document.getElementById("turtlebotTable").style.display="block";
    document.getElementById("alertText").style.display="block";
}

function changeHintText(text) {
	document.getElementById('setupText').innerHTML= "<br>" + text;
}

function changeAlertText() {
	var text;
	var connected;
	var stopped;
	var obstructed;
	
	if (control_connected_rx ) {
	    connected = "<b style='color:yellow;font-size:10pt'>" + "[connected]";
	    if (!control_retransmit) tryHideMotorControls();
	}
	else {
	    connected = "<b style='color:green;font-size:10pt'>" + "[free]";
	    tryShowMotorControls();
	}
	
	if (control_stopped_rx) { 
	    stopped = "<b style='color:red;font-size:10pt'>" + "[stopped]";
	    changeButtonSrc(button_center_src_error);
	}
	else {
	    stopped = "<b style='color:green;font-size:10pt'>" + "[running]";
	    changeButtonSrc(button_center_src_start);
	}
	if (control_stream_rx) {
	    stopped = "<b style='color:green;font-size:10pt'>" + "[stream]";
	}
	if (control_obstructed && control_msgtype_rx == MSG_RESERVED ) {
	    obstructed = "<b style='color:red;font-size:10pt'>" + control_obstructed_string ;//"[blocked]";
	}
	else obstructed = "<b style='color:green;font-size:10pt'>" + "[clear]";
	
	if (control_msgtype_rx == MSG_STRING) {
	    obstructed = "<b style='color:green;font-size:10pt'>" + "[string]";
	}
	else if (control_msgtype_rx == MSG_TWIST) {
	    obstructed = "<b style='color:green;font-size:10pt'>" + "[twist]";
	}
	text =  connected + "</b> "  + stopped + "</b> " + obstructed + "</b> " ;
	document.getElementById('alertText').innerHTML= text;
}

function changeButtonPic(button_html) {
	document.getElementById('middleButtonHtml').innerHTML = button_html;
}

function changeButtonSrc(url) {
	document.getElementById('middleButtonSrc').src = url;
}

function formJSONClick(operation) {
	tx_operation = operation; 
	tx_number ++;
	tx_number = tx_number % mod_base;
	//tx_number = 0; // disable old sequence checking
	;//console.log(operation);
	makeText = JSON.stringify(makeJSONCommand(operation,  tx_number) ) ;
	;//console.log( makeText );
	if (! gapi_loaded ) {
	    trySetupROS();
	    control_msgtype = MSG_TWIST;
	    retransmitEvent(makeJSONCommand(operation, tx_number));
	}
	try {	
		gapi.hangout.data.setValue( tx_gapi_key, makeText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Click");
	}
}

function formJSONError() {
	if (!control_retransmit ) return;
	var connect = control_connected_motors;
	var stopped = control_stopped;
	var kinect = 0;//control_obstructed;
	var stream = false;
	
    if (control_obstructed_num > 0) {
        kinect = control_obstructed_num;
    }
    if (control_retransmit && control_stream) {
        stream = true;
    }
    
	makeText = JSON.stringify(makeJSONError(connect, stopped, kinect, stream));
	try {
		gapi.hangout.data.setValue( tx_gapi_error, makeText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Error");
	}
}

function formJSONControllerName() {
    makeText = JSON.stringify(makeJSONName());
	try {
		gapi.hangout.data.setValue( tx_gapi_controller_name, makeText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Error");
	}
	;//console.log("pad " + makeText);
}

function formJSONTurtlebotName() {
    makeText = JSON.stringify(makeJSONName());
	try {
		gapi.hangout.data.setValue( tx_gapi_turtlebot_name, makeText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Error");
	}
	;//console.log("machine " + makeText);
}

function makeJSONCommand(operation, num ) {
	var myJSON = { "direction" : operation , "number" : num }; 
	return myJSON;
}

function makeJSONError(connected, stopped, kinect, stream) {
	var myJSON = { "connected" : connected , // identify the robot node
	    "stopped" : stopped ,  // is sequence number wrong (see stream)
	    "kinect" : kinect ,  // output from the kinect on the robot (see msg type info)
	    "stream" : stream , // is stream set on robot
	    "msgtype" : control_msgtype  }; // included for status message on robot only
	return myJSON;
}

function makeJSONName() {
    var myData = gapi.hangout.getLocalParticipantId();
    ;//console.log(myData)
    var myJSON = {"data" : myData};
    return myJSON;
}

function isMatchingName(tx_gapi_data) {
    try {
		rx_data = gapi.hangout.data.getState()[tx_gapi_data];
	}
	catch (e) {
		;//console.log("error google hangouts api -- " + tx_gapi_data);
	}
	try {
		rx_id = gapi.hangout.getLocalParticipantId();
	}
	catch (e) {
		;//console.log("error google hangouts api -- " + tx_gapi_data);
	}
	if (typeof rx_data !== 'undefined' && typeof rx_id !== 'undefined') {
	    ;//console.log(rx_error + " error msg");
	    var rx_data_parsed = JSON.parse(rx_data);
	    if (rx_id === rx_data_parsed.data) return true;
	    else return false;
	}
	return false;
}

function isUnsetName(tx_gapi_data) {
    try {
		rx_data = gapi.hangout.data.getState()[tx_gapi_data];
	}
	catch (e) {
		;//console.log("error google hangouts api -- " + tx_gapi_data);
	}
	if (typeof rx_data === 'undefined') {

	    ;//console.log("unset name test - true");
	    return true;
	}
	else {
	    ;//console.log("unset name test - false");
	    return false;
	}
}

function recieveEvent () {
	
	// error data from hangouts...
	try {
		rx_error = gapi.hangout.data.getState()[tx_gapi_error];
		;//console.log(rx_error + " error msg");
	}
	catch (e) {
		;//console.log("error google hangouts api -- " + tx_gapi_error);
	}
	if (typeof rx_error !== 'undefined'){// && rx_error != rx_error_old || true) {
		rx_error_obj = JSON.parse(rx_error);
		if (rx_error_obj.connected == true) control_connected_rx = true;
		else control_connected_rx = false;
		if (rx_error_obj.stopped == true) {
		    control_stopped_rx = true;
		    control_stopped = true;
		}
		else {
		    control_stopped_rx = false;
		    control_stopped = false;
		}
		if (rx_error_obj.kinect > 0) control_obstructed = true;
		else control_obstructed = false;
		if (rx_error_obj.stream) {
		    control_stream_rx = true;
		}
		if (rx_error_obj.msgtype != 0) {
		    control_msgtype_rx = rx_error_obj.msgtype;
		}
		rx_error_old = rx_error;
	}
	changeAlertText();

	// direction data from hangouts...
	try {
	    rx_data = gapi.hangout.data.getState()[tx_gapi_key];
	    
	}
	catch (e){
	    ;//console.log("error google hangouts api -- " );
	}
	;//console.log(rx_data + " key msg");
	
	stream_num ++;
	stream_num = (stream_num ) % mod_base;
	
	if (typeof rx_data !== 'undefined' && ( rx_data != rx_data_old || rx_obj.direction == "stop")) { 
	
		rx_obj = JSON.parse(rx_data) ;	
		
        gapi.hangout.data.clearValue(tx_gapi_key);
        
		// change sequence numbers...
		
		if (rx_obj.direction == "stop" || rx_obj.number == 0 || true) {
		    stream_num = 0;
		    control_stopped = false;
		    control_stopped_rx = false;
		    rx_obj.number = 0;
		}
        ;//console.log("stream = " + stream_num);
		;//console.log( rx_obj.direction + " -- " + rx_obj.number);
		
		// handle stream setting here...
		if ((!control_stream && control_retransmit && 
		        rx_obj.number != stream_num && rx_obj.number != 0)) {
			control_stopped = true;
			changeButtonSrc(button_center_src_error);
			formJSONError(); // OK??
			;//console.log("exit -- bad seq num");
			rx_data_old = rx_data;
			return;
		}
		rx_data_old = rx_data;
		formJSONError();
		if(control_retransmit == true) retransmitEvent(rx_obj);
	}
	// -- set debug var test_config --
	var users;
	try {
	    users = gapi.hangout.getParticipants();
	}
	catch (e) {
	    ;//console.log("bad users list");
	}
	if (users.length <= 1) test_config = true;
	else test_config = false;
	// -- check if names are set, re-arrange screen --
	if (! isUnsetName(tx_gapi_controller_name)) {
	    if (isMatchingName(tx_gapi_controller_name)) {
	        tryShowPadControls();
	    }
	    else {
	        tryHidePadControls();
	        tryHidePadSelectControls();
	    }
	}
	else {
	    // -- controller has not been selected yet --
	    tryShowPadControls();
	    tryShowPadSelectControls();
	}
	if (! isUnsetName(tx_gapi_turtlebot_name)) {
	    if (isMatchingName(tx_gapi_turtlebot_name)) {
	        tryShowMotorControls();
	        tryHidePadControls();
	        tryHidePadSelectControls();
	    }
	    else {
	        tryHideMotorControls();
	        if (isUnsetName(tx_gapi_controller_name)) {
	            tryShowPadControls();
	            tryShowPadSelectControls();
	        }
	    }
	}
	else {
	    if (true) {
	        tryShowMotorControls();
	        tryShowPadControls();
	        tryHidePadSelectControls();
	    }
	   
	}
	if (test_config && ! isUnsetName(tx_gapi_turtlebot_name)) {
	    tryShowMotorControls();
	    tryShowPadControls();
	    tryShowPadSelectControls();
	    ;//console.log("test config setting");
	}
	
	
	receiveMapEvent();
	receiveMapBroadcast();
	
}

function retransmitEvent(data) {
	;//console.log(data.direction + " -- retransmit");
	var numLinear = 0;
	var numAngular = 0;
	
	switch(data.direction) {
		case "left":
			numAngular = 1;
			
		break;
		
		case "right":
			numAngular = -1;
		break;
		
		case "up":
			if (last_key === "up" && last_counter < speed_max ) {
				last_counter ++ ;
				setSpeedTimer();
			} 
			else if (timer_key == 0) last_counter = 1;
			numLinear = 0.20; // 
		break;
		
		case "down":
			if (last_key === "down" && last_counter < speed_max ) {
				last_counter ++ ;
				setSpeedTimer();
			}
			else if (timer_key == 0) last_counter = 1;
			numLinear = -0.20; // 
		break;
		
		case "stop":
			numAngular = 0;
			numLinear = 0;
		break;
	}
	
	last_key = data.direction;
	///////////////////////
	
	switch (control_msgtype) {
		case MSG_STRING:
			
  			var string = new ROSLIB.Message({ data: "hello " + data.direction });
			
			cmdVel.publish(string);
			
			;//console.log("no error? -- string");
			
		break;
		
		case MSG_TWIST:

			/* 
			turtlebot_bringup (?)
			roslaunch turtlebot_bringup minimal.launch
			always launch software first then connect turtlebot!!
			*/
  			
  			var twist = new ROSLIB.Message({
    			linear : {
      			x : numLinear * last_counter,
      			y : 0.0,
      			z : 0.0
    			},
    			angular : {
     			x : 0.0,
      			y : 0.0,
      			z : numAngular
    			}
  			});
  				

			cmdVel2.publish(twist);

			;//console.log("no error? -- twist");

		break;
		
		case MSG_RESERVED:
			
  			var velocity = new ROSLIB.Message({
    			header : {
    			    seq : 0, //
    			    stamp : 0,
    			    frame_id : "0"
    			},
    			twist : {
    			    linear : {
      			    x : numLinear * last_counter,
      			    y : 0.0,
      			    z : 0.0
    			    },
    			    angular : {
     			    x : 0.0,
      			    y : 0.0,
      			    z : numAngular
    			    }
  			    }
    			
  			});
  				

			cmdVel3.publish(velocity);

			;//console.log("no error? -- velocity");
		break;
	}
	
}

function setSpeedTimer() {
	if (timer_key != 0) {
		clearTimeout(timer_key);
	}
	else {
		last_counter = 1;
	}
	timer_key = setTimeout(doSpeedTimer, 700);
}

function doSpeedTimer() {
	last_counter = 1;
	timer_key = 0;
}

function setKinectListener() {
    //;//console.log("kinect setup");
  	
  	try {
  	    kinect_listener.subscribe( function(message) {
            //;//console.log(  kinect_listener.name + " : " + message.data );
            var data = message.data;
            control_obstructed_num = message.data;
            control_obstructed_string = "[";
            if (data > 7) {
                control_obstructed_string = "[xxx]";
                data = 0;
            }
            // read message
            if (data >= 4) {
                control_obstructed_string += "x";
                data -= 4;
            }
            else { control_obstructed_string += "-";}
            if (data >= 2) {
                control_obstructed_string += "x";
                data -= 2;
            }
            else { control_obstructed_string += "-";}
            if (data >= 1) {
                control_obstructed_string += "x";
                data -= 1;
            }
            else { control_obstructed_string += "-";}
            
            control_obstructed_string += "]";
        } );
    }
    catch (e) {
        ;//console.log ("no message " + e.message);
    }


}


    

// A function to be run at app initialization time which registers our callbacks
function init() {
	;//console.log('Init app.');

	var apiReady = function(eventObj) {
		if (eventObj.isApiReady) {
			console.log('API is ready v1.11 --------------------------------');
	
			gapi.hangout.data.onStateChanged.add(function(eventObj) {
				recieveEvent();
			});
	        
			//;//console.log("websocket test");
			if ('WebSocket' in window){
    				// WebSocket is supported.
			
			} else {
    				// WebSockets are not supported.
				alert("no web sockets.");
			}
            
            //setKinectListener();
            gapi_loaded = true;
            
      			gapi.hangout.onApiReady.remove(apiReady);
    		}
	};

	// Use this special api ready state event
	gapi.hangout.onApiReady.add(apiReady);
}

gadgets.util.registerOnLoadHandler(init);

// app-map.js
var forbiddenCharacters = /[^a-zA-Z!0-9_\- ]/;
var test_map = "";
var app_name = "";
var app_msg = "";
var app_stopping = false;
var map_image ;
var map_overlay ;
var coord_x = 0;
var coord_y = 0;
var map_manager_started = false;
var map_nav_started = false;
var app_manager = true;

var tx_gapi_map_event = "telenp_map";
var tx_gapi_app_list = "telenp_app_list";
var map_service_list ;
var map_service_load ;
var map_service_new ;
var map_service_pic ;
var map_service_delete ;
var map_service_rename ;
var map_service_save ;
var map_service_start ;
var map_service_stop ;
var map_service_info ;
var map_service_all ;
var map_initialpose ;
var map_goal_pose ;
// listen to map topic.
var map_listener ;
var map_meta_data ;
// app stuff
var app_topic_list;
var app_service_status;
var app_service_start;
var app_service_stop;
var app_service_invite;

// commands for operations
var map_command_load = "load";
var map_command_make = "new";
var map_command_delete = "delete";
var map_command_rename = "rename";
var map_command_save = "save";
var map_command_list = "list";
var map_command_pic = "pic";
var map_command_meta = "mapmeta";
// more commands for lists that are needed in above ops.
var map_command_list_load = "embedded_list_for_load";
var map_command_list_delete = "embedded_list_for_delete";
var map_command_list_rename = "embedded_list_for_rename";
var map_command_list_start = "embedded_list_for_show_map";
var map_command_list_view = "embedded_list_for_view_map";
// comands for working with apps.
var app_command_list = "app_list";
var app_command_invite = "app_invite";
var app_command_make_map = "app_makemap";
var app_command_app_stop = "app_appstop";
var app_command_map_manager = "app_mapmanage";
var app_command_map_manager_force = "app_mapmanage_force";
var app_command_map_nav = "app_mapnav";
var app_command_map_nav_force = "app_mapnav_force";
var app_command_no_op = "app_no_op";
var map_command_nav_execute = "app_mapnav_execute";
var map_command_nav_start = "app_mapnav_start";
var map_command_nav_goal = "app_mapnav_goal";
var map_command_library_force = "map_library_force";
// constants for app names
var app_manager_teleop = "tele_presence/teleop";
var app_manager_mapping = "tele_presence/mapping";
var app_manager_navigate = "tele_presence/navigate";
// enum for planning map movement
var ENUM_BOT_START = "turtlebot_place_start";
var ENUM_BOT_END = "turtlebot_place_end";
var ENUM_BOT_NONE = "turtlebot_no_op";
var nav_map_setup = ENUM_BOT_NONE;
// enum for map service
var ENUM_LIST = 0;
var ENUM_SAVE = 1;
var ENUM_RENAME = 2;
var ENUM_DELETE = 3;
var ENUM_PUBLISH = 4;
// pose and goal
var map_nav_pose_x = 0;
var map_nav_pose_y = 0;
var map_nav_pose_z = 0;
var map_nav_pose_a = 0;
var map_nav_goal_x = 0;
var map_nav_goal_y = 0;
var map_nav_goal_z = 0;
var map_nav_goal_a = 0;
// center of map
var map_nav_origin_x = 0; //these vars should be loaded when the map refreshes.
var map_nav_origin_y = 0;
var map_nav_origin_z = 0;
var map_nav_origin_ax = 0;
var map_nav_origin_ay = 0;
var map_nav_origin_az = 0;
var map_nav_resolution = 0.05;

var angle_count_start = 0; //
var angle_count_stop = 0;  //


function opChooseOp() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "block";
    document.getElementById("wizOpView").style.display = "none";
    
    document.getElementById("wizOpList").style.display = "none";

}

function opChoose() {
    sendMapCommandsShort(map_command_list, 0, "", "", map_command_list);
}

function opLoad() {
    document.getElementById("wizOpLoad").style.display = "block";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById("wizOpLoadConfirm").style.display = "none";
    
    document.getElementById("wizOpLoadNavConfirm").style.display = "none";
    
    sendMapCommandsShort(map_command_list, 0, "", "", map_command_list_load);
}

function opMake() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "block";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById("wizOpNewConfirm").style.display = "none";

}

function opDelete() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "block";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById("wizOpDelConfirm").style.display = "none";
    
    

    sendMapCommandsShort(map_command_list, 0, "", "", map_command_list_delete);
}

function opRename() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "block";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById("wizOpRenameConfirm").style.display = "none";
    document.getElementById("inputSpaceRename").value = "";
    


    sendMapCommandsShort(map_command_list, 0, "", "", map_command_list_rename);
}

function opSave() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "block";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";    
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById("wizOpSaveConfirm").style.display = "none";
    document.getElementById("inputSpaceSave").value = "";
    
    document.getElementById("wizOpSaveConfirm").style.display = "none";
    

}

function opStart() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "block";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById('wizOpStartConfirm').style.display = "none";
    document.getElementById('wizOpStartConfirmForce').style.display = "none";    
    //app_command_map_manager
    //sendMapCommandsShort(app_command_map_manager, 0, "", "", app_command_map_manager);
}

function opView() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "block";
    document.getElementById("wizOpList").style.display = "none";
    document.getElementById('wizOpViewConfirm').style.display = "none";
    

}

function opList() {
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "none";
    document.getElementById("wizOpView").style.display = "none";
    document.getElementById("wizOpList").style.display = "block";
    document.getElementById('wizOpViewConfirm').style.display = "none";
    

}

function opCancel() {
    //opChooseOp();
    document.getElementById("wizOpLoad").style.display = "none";
    document.getElementById("wizOpNew").style.display = "none";
    document.getElementById("wizOpDel").style.display = "none";
    document.getElementById("wizOpRename").style.display = "none";
    document.getElementById("wizOpSave").style.display = "none";
    document.getElementById("wizOpDone").style.display = "none";
    document.getElementById("wizOpStart").style.display = "none";
    document.getElementById("wizChooseOp").style.display = "block";
    document.getElementById("wizOpView").style.display = "none";
    
    document.getElementById("wizOpList").style.display = "none";
}

function disableNONE() {
    document.getElementById("opMake").disabled = '';
    document.getElementById("opSave").disabled = '';
    document.getElementById("opLoad").disabled = '';
    //document.getElementById("opChoose").disabled = '';//'disabled';
    document.getElementById("opStart").disabled = '';
    document.getElementById("opRename").disabled = '';
    document.getElementById("opDelete").disabled = '';
    document.getElementById("opList").disabled = '';    

}

function disableGMAP() {
    document.getElementById("opMake").disabled = 'disabled';
    document.getElementById("opSave").disabled = 'disabled';
    document.getElementById("opLoad").disabled = '';
    //document.getElementById("opChoose").disabled = '';//'disabled';
    document.getElementById("opStart").disabled = '';
    document.getElementById("opRename").disabled = '';
    document.getElementById("opDelete").disabled = '';
    document.getElementById("opList").disabled = '';    

}

function disableAMCL() {
    document.getElementById("opMake").disabled = '';
    document.getElementById("opSave").disabled = '';
    document.getElementById("opLoad").disabled = 'disabled';
    //document.getElementById("opChoose").disabled = '';//'disabled';
    document.getElementById("opStart").disabled = '';
    document.getElementById("opRename").disabled = '';
    document.getElementById("opDelete").disabled = '';
    document.getElementById("opList").disabled = '';    

}

function receiveMapEvent() {
    ;//console.log("map");
    if (! isMatchingName(tx_gapi_turtlebot_name)) return;
    var rx_map_commands ;
    try {
	    rx_map_commands = gapi.hangout.data.getState()[tx_gapi_map_event];
	    
	}
	catch (e){
	    console.log("error google hangouts api -- map" );
	}
	if (typeof rx_map_commands !== "undefined") {
	    var commands = JSON.parse(rx_map_commands);
	    
	            var start = new Array();
	            if ( ( app_command_map_nav_force != commands.command && 
	                    app_command_make_map != commands.command &&
	                    app_command_map_nav != commands.command &&
	                    app_command_app_stop != commands.command &&
	                    map_command_load != commands.command ) || 
	                    
	                    (app_name == app_manager_navigate && 
	                    map_command_load == commands.command)
	                    ) {
	                
                    parseCommands(commands);
                }
                else {
                        
                        var request = new ROSLIB.ServiceRequest({});
	                    app_service_stop.callService( request, function (result) {
	                        app_name = "stop";
	                        parseCommands(commands);
	                    } );
	                    
	                //} );
                }
                
	} 
	else {
	    console.log("google prob?? or just no data...");
	}// 
} //     
	    
function parseCommands(commands) {
    if (true) {
	    //do something... round-trip the 'wizard' operand
	    switch( commands.command ) {
	        case map_command_list : 
	            
	        
	            var request = new ROSLIB.ServiceRequest({'op': ENUM_LIST});
	            map_service_all.callService( request, function (result) {
	            //map_service_list.callService(...
	                sendMapBroadcast(commands.wizard, result.map_list, 0);
	            });
	        break;
	        
	        case map_command_load : 
	            // must start nav automatically with load!
	            var start = app_manager_navigate;

                if (app_name == app_manager_navigate ) {
                    // if already navigate, do not relaunch...
                    var request = new ROSLIB.ServiceRequest({ 'op' : ENUM_PUBLISH, 
                        "map_id": commands.id});
                    map_service_all.callService( request, function (result) {
                        console.log(result);
                        sendMapBroadcast(commands.wizard, null, 0);
                    } );
                    return;
                }
                var request = new ROSLIB.ServiceRequest({'name': start});
	            app_service_start.callService( request, function (result) {
	                // nothing here... 
	                console.log("try " + start + " " + result.message);
	                
                    map_nav_started = true;
                    app_name = app_manager_navigate;
	                //} ); // inner block...
	                
	                /////////////////
	                setTimeout( function() { ///////REMOVE ME??
	                
	                    var request = new ROSLIB.ServiceRequest({ 'op' : ENUM_PUBLISH, 
	                        "map_id": commands.id});
	                    map_service_all.callService( request, function (result) {
	                        console.log(result);
	                        sendMapBroadcast(commands.wizard, null, 0);
	                    } );
	                
	                },10000);///////REMOVE ME??
	                
	            
	            });// closing block for navigate start...
	            
	        break;
	        
	        
	        case map_command_delete :
                var request = new ROSLIB.ServiceRequest({ 'op' : ENUM_DELETE ,
                    "map_id": commands.id});
	            map_service_all.callService( request, function (result) {
	                sendMapBroadcast(commands.wizard, null, 0);
	            } );
	        
	        
	        break;
	        
	        case map_command_rename :
                var request = new ROSLIB.ServiceRequest({ 'op' : ENUM_RENAME , 
                    "map_id": commands.id, 
                    "name": commands.rename});
	            map_service_all.callService( request, function (result) {
	                sendMapBroadcast(commands.wizard, null, 0);
	            } );
	        
	        
	        break;
	        
	        case map_command_save :
	        
                
                var save_count = 0;
                
	            
                var request = new ROSLIB.ServiceRequest({ 'op': ENUM_SAVE,
                    "name": commands.new_name});
	            map_service_all.callService( request, function (result) {
	                sendMapBroadcast(commands.wizard, null, 0);
	                ;//
	                //console.log("---map_name---  " + commands.new_name);
	            } );
	            
	            
	        break;
	        
	        case map_command_make :
                var request = new ROSLIB.ServiceRequest({"width": 100, "height":250});
	            map_service_new.callService( request, function (result) {
	                sendMapBroadcast(commands.wizard, null, 0);
	                console.log('new map');
	            } );
	        break;

            case map_command_pic :
            
                var resolution;
                var width;
                var height;
                console.log("read map data...");
                map_listener.subscribe( function (result1) {
	                map_listener.unsubscribe();
	                resolution = result1.info.resolution;
	                width = result1.info.width;
	                height = result1.info.height;
	                console.log("find meta data... "+ width +"," + height);
	                map_nav_resolution = resolution;
	            //});
            
                    var request = new ROSLIB.ServiceRequest({
                        'width' : width,
                        'height' : height
                    });
	                map_service_pic.callService( request, function (result2) {
	                    //do all picture things here.
	                    /* remove some pic stuff here */
	                    sendMapInForm(result2.data);
	                    var list = new Array(JSON.stringify(result1.info));
	                    sendMapBroadcast(commands.wizard, list, 0);

	                    //console.log("meta data -- " + list[0]);
	                    
	                } );
	            
	            });
	        break;
            
            
            case app_command_make_map :
                // GMAPPING
                app_name = app_manager_mapping;
                
                var start = app_manager_mapping;
                
                var request = new ROSLIB.ServiceRequest({'name': start});
	            app_service_start.callService( request, function (result) {
	                // nothing here... 
	                console.log("try " + start + " " + result.message);
	                sendMapBroadcast(commands.wizard, null, 0);
	            } );
                
                
                
            break;
            
            case app_command_map_manager :
            break;
            
            case app_command_map_manager_force :
                
                var request = new ROSLIB.ServiceRequest({'op' : ENUM_LIST });
	            map_service_all.callService( request, function (result) {
	                
	                sendMapBroadcast(commands.wizard, result.map_list, 0);
	                var x = 0;
	                for (x = 0; x < result.map_list.length; x ++) {
	                    if (result.map_list[x].name == "" || 
	                            typeof result.map_list[x].name === 'undefined') {
	                        //delete map...
	                        var request = new ROSLIB.ServiceRequest({ 'op' : ENUM_DELETE ,
	                            "map_id": result.map_list[x].map_id });
	                        map_service_all.callService( request, function (result) {
                                console.log("delete map: " + x);
	                        } );
	                    }
	                }
	            });
	            
            break;
            
            case app_command_map_nav :
            case app_command_map_nav_force:
                
                var start = app_manager_navigate;
                app_name = app_manager_navigate;
                var request = new ROSLIB.ServiceRequest({'name': start});
	            app_service_start.callService( request, function (result) {
	                // nothing here... 
	                console.log("try " + start + " " + result.message);
	                sendMapBroadcast(commands.wizard, null, 0);
                    map_nav_started = true;
	            } );
                
                
                
            break;
            
            case app_command_app_stop :
            
                var start = app_manager_teleop;
                //"tele_presence/teleop";
                app_name = app_manager_teleop;
                var request = new ROSLIB.ServiceRequest({'name': start});
	            app_service_start.callService( request, function (result) {
	                // nothing here... START TELEOP ALWAYS...
	                console.log("try " + start + " " + result.message);
	                sendMapBroadcast(commands.wizard, null, 0);
	            } );
                
                
                
            break;
            
            case map_command_meta:
                /*
                
	            */
            break;
            
            case app_command_no_op :
                //NO OPERATION HERE
            break;
            
            case map_command_nav_execute :
            
                map_nav_pose_x = commands.x1;
                map_nav_pose_y = commands.y1;
                map_nav_pose_z = 0;
                map_nav_pose_a = commands.angle1;
                map_nav_goal_x = commands.x2;
                map_nav_goal_y = commands.y2;
                map_nav_goal_z = 0;
                map_nav_goal_a = commands.angle2;
            
                if (commands.x1 != commands.x2 ||
                    commands.y1 != commands.y2 || 
                    commands.angle1 != commands.angle2) {
                    
                    sendInitialPose(commands.x1, commands.y1, 0,  commands.angle1);
                    
                    sendGoalPose(commands.x2, commands.y2, 0, commands.angle2);
                    
                }
                
                sendMapBroadcast(commands.wizard, null, 0);
            break;
            
            case map_command_nav_start :
            
                map_nav_pose_x = commands.x1;
                map_nav_pose_y = commands.y1;
                map_nav_pose_z = 0;
                map_nav_pose_a = commands.angle1;
                
            
                sendInitialPose(commands.x1, commands.y1, 0,  commands.angle1);
                sendMapBroadcast(commands.wizard, null, 0);
            break;
            
            case map_command_nav_goal :
            
                
                map_nav_goal_x = commands.x2;
                map_nav_goal_y = commands.y2;
                map_nav_goal_z = 0;
                map_nav_goal_a = commands.angle2;

                sendGoalPose(commands.x2, commands.y2, 0, commands.angle2);
                sendMapBroadcast(commands.wizard, null, 0);
            break;
	    }
	}
	
	
    gapi.hangout.data.clearValue(tx_gapi_map_event);
    
}

function logArray(start) {
    var x = 0;
    var s = "";
    var l = start.length;
    for( x = 0; x < l; x ++) {
        s = s + start[x] + " ";
    }
    console.log(" array : " + s);
}

function sendMapInForm(data) {
    if (typeof data === "undefined") data = "--";
    $.ajax({
        url: "//awesometelenp.appspot.com/",
        type: "POST" ,
        dataType: 'json',
        data: {
            'map': data},
        success: function( ret ) {
            //
            //var mapspace = $('#showMapSpaceView');
            var mapspace = $('#showMapSpaceDiv');
            mapspace.html('<img id="mapimg" src="' + ret.picurl + '">');
            
            mapspace.ready(showToolTip);
            mapspace.click(takePosition);
            
        }
    });
    
}

function sendMapCommandsShort( command, id, name1, name2, wizard) {
    sendMapCommands(command, id, name1, name2, wizard, 0,0,0, 0,0,0);
}

function sendMapCommands( command, id,  name1, name2, wizard , 
        xx1, yy1, angle1, xx2, yy2, angle2) {
    if (! isMatchingName(tx_gapi_turtlebot_name) && 
            ! isMatchingName(tx_gapi_controller_name) ) return;
    var send = {
                    'command' : command,
                    'id' : id,
                    'new_name' : name1,
                    'rename' : name2,
                    'wizard' : wizard,
                    //extra ops
                    "x1" : xx1,
                    "y1" : yy1,
                    "angle1" : angle1,
                    "x2" : xx2,
                    "y2" : yy2,
                    "angle2" : angle2 };
                    
                    
    var makeText = JSON.stringify (send);
    
    try {
		gapi.hangout.data.setValue( tx_gapi_map_event, makeText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Error");
	}
	;//console.log("map event short" + makeText);
}

function setMapServices( rootname ) {
    if (typeof rootname === "undefined") rootname = "";

  	
  	map_service_list = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + 
    	rootname + '/list_map',
   		 serviceType : 'tele_presence/MapList'
  	});
  	
  	
  	map_service_load = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + rootname + 
    	//'/load_map_db',
    	'/load_map',
   		 serviceType : 'tele_presence/MapLoad'
  	});
  	
  	// service for new map
  	map_service_new = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix +  '/new_map',
   		 serviceType : 'tele_presence/CreateMap'
  	});
  	
  	map_service_pic = new ROSLIB.Service({
    	'ros' : ros,
    	'name' :app_manager_prefix +  '/picture_map',
   		 serviceType : 'tele_presence/PictureMap'
  	});
  	
  	//launch
  	map_service_start = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/basic_launch',
   		 serviceType : 'tele_presence/BasicLaunch'
  	});
  	
  	//stop
  	map_service_stop = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/basic_stop',
   		 serviceType : 'tele_presence/BasicStop'
  	});
  	
  	map_service_delete = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + rootname + '/delete_map',
   		 serviceType : 'tele_presence/MapDelete'
  	});
  	
  	map_service_rename = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + rootname + '/rename_map',
   		 serviceType : 'tele_presence/MapRename'
  	});
  	
  	map_service_save = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/save_map',
   		 serviceType : 'tele_presence/MapSave'
  	});
  	
  	map_service_all = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/map_all',
   		 serviceType : 'tele_presence/MapUniversal'
  	});
  	
  	map_listener = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/map',
   		 messageType : 'nav_msgs/OccupancyGrid'
   		 
  	});
  	
  	map_meta_data = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/map_metadata',
   		 messageType : 'nav_msgs/MapMetaData'
   		 
  	});
  	
  	/*
  	map_service_info = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/map_info',
   		 messageType : 'tele_presence/MapInfo'
  	});
  	*/
  	
  	map_initialpose = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/initialpose',
   		 messageType : 'geometry_msgs/PoseWithCovarianceStamped'
   		 
  	});
  	
  	/*
  	map_goal_pose = new ROSLIB.ActionClient({
  	    'ros': ros,
  	    'serverName' : app_manager_prefix + '/move_base/goal',
  	    'actionName' : 'move_base_msgs/MoveBaseAction'
  	});
  	*/
  	
  	// ROCON-APP-MANAGER SERVICES
  	app_topic_list = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : '/app_manager/app_list',
   		 messageType : 'rocon_app_manager_msgs/AppList'
  	});
  	
  	app_service_start = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : '/app_manager/start_app',
   		 serviceType : 'rocon_app_manager_msgs/StartApp'
  	});
  	
  	app_service_stop = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : '/app_manager/stop_app',
   		 serviceType : 'rocon_app_manager_msgs/StopApp'
  	});
  	
  	app_service_invite = new ROSLIB.Service({
    	'ros' : ros,
    	'name' : '/app_manager/simple_invite',
   		 serviceType : 'rocon_app_manager_msgs/SimpleInvite'
  	});
}

function sendAppServiceTxt() {
    console.log("list to follow !!");
    //var request = new ROSLIB.ServiceRequest({});
	app_topic_list.subscribe( function (find) {
	    var x = 0;
	    var result = find.available_apps;
	    for(x = 0; x < result.length; x ++) {
	        console.log(result[x].name + " -- ");
	    }
	    console.log("runnning to follow !!");
	    var result = find.running_apps;
	    for(x = 0; x < result.length; x ++) {
	        console.log(result[x].name + " -- ");
	    }
	    app_topic_list.unsubscribe();
	} );
}

function inviteAndInit() {
    var start = app_manager_teleop;
    //"tele_presence_apps/teleop";
    var request = new ROSLIB.ServiceRequest({'name': start});
	app_service_start.callService( request, function (result) {
	    // nothing here... START TELEOP ALWAYS...
	} );
}

function putListInSelectLocal(list, space) {
    var string = "";
    var x;
    for(x =0; x < list.length; x ++ ) { 
        string = string + '<option value="' + list[x].map_id;
        var num = x + 1;
        string = string + '">' + num + '. ' + list[x].name  ;
        if (list[x].name == "") string = string + "[unnamed]";
        string = string + "</option>";
        
    }
    ;//console.log(string);
    document.getElementById(space).innerHTML = string;
}

function putListInBoxLocal(list, space) {
    var string = "";
    var x;
    for(x =0; x < list.length; x ++ ) { 
        var num = x + 1;
        string = string + num + ". " ;
        string = string + list[x].name;
        if (list[x].name == "") string = string + "[unnamed]";
        string = string + "<br>";
        //console.log("list -" + list[x].name + "- " + list[x].map_id);
    }

    document.getElementById(space).innerHTML = string;
}



function sendMapBroadcast(type, list, num) {
    if (! isMatchingName(tx_gapi_turtlebot_name)  ) return;
    var x;
    var map_list = "";
    if(type === map_command_meta || type === map_command_pic ) {
        map_list = JSON.stringify ({ 
                            'name' : list[0] ,
                            'session_id' : '' ,
                            'date' : '' , 
                            'map_id' : ''
        });
    }
    else if (list == null || typeof list === "undefined") {
        map_list = JSON.stringify ({ 
                            'name' : '' ,
                            'session_id' : '' ,
                            'date' : '' , 
                            'map_id' : ''
        });
    }
    else if (list != null) {
        newlength = list.length;
        if (list.length > 20) newlength = 20;
        for (x = 0; x < newlength; x ++) {
            var map_name = list[x].name;
            if (list.length != newlength && x == newlength - 1) {
                map_name = '[' +( list.length - newlength )+ ' more in list...]';
            }
            var element = { 'name' : map_name, //list[x].name ,
                            'session_id' : list[x].session_id ,
                            'date' : list[x].date , 
                            'map_id' : list[x].map_id };
            if (x != 0) map_list = map_list + ","; 
            map_list = map_list +  JSON.stringify(element);
        }
    }
    if (num == 0 && list != null && typeof list !== "undefined") num = list.length;
    
    map_list = "[" + map_list + "]";
    var listText = '{"type":"'+type+'","map_list":'+ map_list + ', "num":'+num + '}';
    ;//console.log (listText);
    try {
		gapi.hangout.data.setValue( tx_gapi_list, listText);
	}
	catch (e) {
		;//console.log("hangout setValue error. -- Error");
	}
	;//console.log("map event " + listText);
}



function receiveMapBroadcast() {
    if (! isMatchingName(tx_gapi_controller_name)  ) return;
    try {
	    rx_data = gapi.hangout.data.getState()[tx_gapi_list];
	    
	}
	catch (e){
	    ;//console.log("error google hangouts api -- " );
	}
	;//console.log(rx_data + " list msg");
	
	if (typeof rx_data !== "undefined") {
	    // do something...
	    data = JSON.parse(rx_data);
	    switch(data.type) {
	        case map_command_list :
	            putListInBoxLocal(data.map_list, "listSpace");
	            $('.listLength').html("Items: " + data.num);
	        break;
	        
	        case map_command_load :
	            document.getElementById("wizOpLoadConfirm").style.display = "block";
	            document.getElementById("wizOpLoadNavConfirm").style.display = "none";
	            app_msg = "NAVIGATE A MAP";
	            //opChooseOp();
	        break;
	        
	        case map_command_delete :
	            opDelete();
	            document.getElementById("wizOpDelConfirm").style.display = "block";
	        break;
	        
	        case map_command_list_load :
	            putListInSelectLocal(data.map_list, "selectSpaceLoad");
	            $('.listLength').html("Items: " + data.num);
	        break;
	        
	        case map_command_list_start:
	        
	        break;
	        
	        case map_command_list_delete :
	            putListInSelectLocal(data.map_list, "selectSpaceDelete");
	            $('.listLength').html("Items: " + data.num);
	        break;
	        
	        case map_command_list_rename :
	            putListInSelectLocal(data.map_list, "selectSpaceRename");
	        break;
	        
	        case map_command_rename :
	            document.getElementById("wizOpRenameConfirm").style.display = "block";
	        break;
            
            case map_command_save :
	            document.getElementById("wizOpSaveConfirm").style.display = "block";
	            app_msg = "MAPPING OPS";
	        break;
	        
	        case map_command_make :
	            document.getElementById("wizOpNewConfirm").style.display = "block";
	            app_msg = "TESTING OPS";
	            disableAMCL();
	        break;
	        
	        case app_command_make_map :
	            document.getElementById("wizOpNewConfirm").style.display = "block";
	            app_msg = "MAPPING OPS";
	            disableAMCL();
	        break;
	        

	        case app_command_map_manager_force :
	            document.getElementById("wizOpStartConfirmForce").style.display = "block";
	            disableNONE();
	        break;
	            
	        case app_command_map_manager :
	            document.getElementById("wizOpStartConfirm").style.display = "block";
	            disableNONE();
	        break;
	        
	        case app_command_app_stop :
	            document.getElementById("wizOpList").style.display = "none";
	            app_msg = "";
	            disableNONE();
	        break;
	        
	        case app_command_map_nav:
	            document.getElementById("wizOpLoadNavConfirm").style.display = "block";
	            app_msg = "NAVIGATE A MAP";
	            disableGMAP();
	        break;
	        
	        case map_command_pic :
	            sendMapInForm();
	            setOrigin(data.map_list[0].name);
	        break;
	        
	        case map_command_meta :
	            sendMapInForm();
	            setOrigin(data.map_list[0].name);
	        break;
	        
	        case map_command_nav_execute :
	            app_msg = "NAVIGATE A MAP";
	        break;
	        
	        case map_command_nav_start :
	        
	        break;
	        
	        case map_command_nav_goal :
	        
	        break;
	        
	        case map_command_library_force :
	            sendMapCommandsShort(map_command_list, 0, "", "", map_command_list_load);
	        break;
	    }
	}
	try {
	    gapi.hangout.data.clearValue(tx_gapi_list);
	    
	}
	catch (e){
	    ;//console.log("error google hangouts api -- " );
	}
	
	//print a status msg on screen:
	if (app_msg != "") $('#topstatus').html("[" + app_msg + "]");
	
}

function fixText(text) {
    return text.replace(forbiddenCharacters, '');
}

function executeLoad() {
    var map_id = document.getElementById("selectSpaceLoad").value;
    sendMapCommandsShort(map_command_load, map_id, "", "", map_command_load);
}

function executeDelete() {
    var map_id = document.getElementById("selectSpaceDelete").value;
    sendMapCommandsShort(map_command_delete, map_id, "", "", map_command_delete);
}

function executeRename() {
    var map_id = document.getElementById("selectSpaceRename").value;
    var new_name = fixText(document.getElementById("inputSpaceRename").value);
    //check for bad 'new_name' string (no quotes, etc.)
    sendMapCommandsShort(map_command_rename, map_id, "",new_name, map_command_rename);
}

function executeSave() {
    var new_name = fixText(document.getElementById("inputSpaceSave").value);
    //check for bad 'new_name' string (no quotes, etc.)
    sendMapCommandsShort(map_command_save, 0, new_name, "", map_command_save);
    ;//console.log("save name " + new_name);
}

function executeNew() {
    sendMapCommandsShort(map_command_make, 0, "", "", map_command_make);
}

function executeListApps() {
    sendMapCommandsShort(app_command_list, 0, "", "", app_command_list);
}

function executeMakeMapAndroid() {
    sendMapCommandsShort(app_command_make_map, 0, "", "", app_command_make_map);
}

function executeMapStart() {
    sendMapCommandsShort(app_command_map_manager_force, 0, "", "", app_command_map_manager_force);
}

function executeList() {
    sendMapCommandsShort(map_command_list, 0, "", "", map_command_list);
}

function executeRunNav() {
    document.getElementById('wizOpNavSettings').style.display = "block";
    opView();
    //opViewDisabled();
    disableGMAP();
}

function executeLibraryForce() {
    sendMapCommandsShort(app_command_map_manager_force, 0, "", "", map_command_library_force);
    
}

function executeRunNavForce() {
    
    sendMapCommandsShort(app_command_map_nav_force, 0, "", "", app_command_map_nav);
}

function executeNavStart() {
    var reply = confirm("NAV command! " + "\n\n" + 
        "start: " + map_nav_pose_x.toFixed(2) + "," + map_nav_pose_y.toFixed(2) + "\n" +
        "start angle: " + map_nav_pose_a.toFixed(2) + "\n" +
        
        "send??!!"
    );
    if (!reply) return;
    sendMapCommands(map_command_nav_start, 0, '', '', map_command_nav_start,
            map_nav_pose_x, map_nav_pose_y, map_nav_pose_a,
            0, 0, 0 );
}

function executeNavGoal() {
    var reply = confirm("NAV command! " + "\n\n" + 
        
        "stop: " + map_nav_goal_x.toFixed(2) + "," + map_nav_goal_y.toFixed(2) +"\n" +
        "stop angle: " + map_nav_goal_a.toFixed(2) + "\n" +
        "send??!!"
    );
    if (!reply) return;
    sendMapCommands(map_command_nav_goal, 0, '', '', map_command_nav_goal,
            0, 0, 0,
            map_nav_goal_x, map_nav_goal_y, map_nav_goal_a );
}

function opStopService() {
    sendMapCommandsShort(app_command_app_stop, 0, "", "", app_command_app_stop);
}

function getMapTopic() {
    if (! isMatchingName(tx_gapi_turtlebot_name) && 
        ! isMatchingName(tx_gapi_controller_name) ) return;
    sendMapCommandsShort(map_command_list_start, 0, "", "", map_command_list_start);
    return;

}

function getMapTopicView() {
    if (! isMatchingName(tx_gapi_turtlebot_name) && 
        ! isMatchingName(tx_gapi_controller_name) ) return;
    sendMapCommandsShort(map_command_pic, 0, "", "", map_command_pic);
    // get map meta data here??
    
    return;
}

function setOrigin(data) {
    //console.log(data);
    var origin = JSON.parse(data);
    map_nav_resolution = origin.resolution ; // 
    map_nav_origin_x = origin.origin.position.x; // magic number zero?
    map_nav_origin_y = origin.origin.position.y;
    //console.log(map_nav_resolution);
    alert("map info set at: \n\n" +
        "resolution: " + map_nav_resolution.toFixed(2) + "\n" +
        "origin xy: " + map_nav_origin_x.toFixed(2) + "," + map_nav_origin_y.toFixed(2) );
}

/* start code for placing robot on map... */
function showToolTip() {
    var tooltip = $( '<div id="tooltip">' ).appendTo( 'body' )[0];
    $(tooltip).hide();
    
    $( '#mapimg' ).each(function () {
        var pos = $( this ).position(),
            top = pos.top,
            left = pos.left,
            width = $( this ).width(),
            height = $( this ).height(); 
        $( this ).
            mousemove(function ( e ) {
                var top_y = $('#showMapSpaceView').position().top;
                var scroll_x = $('#showMapSpaceView')[0].scrollLeft;
                var scroll_y = $('#showMapSpaceView')[0].scrollTop;
                var x = e.pageX - left,
                    y = e.pageY - top;
                    //console.log(x + " -- " + y);
                coord_x = (x + scroll_x) ;// 
                coord_y = (y + scroll_y) - top_y ; // 
                    
                $( tooltip ).html( 'position xy = '
                        + ( coord_x ) + ' -- ' +( coord_y ) + '<br/>' + 
                        "mode: " + nav_map_setup ).css({
                    left: e.clientX + 10,
                    top: e.clientY + 10
                }).show();
                
            }).
            mouseleave(function () {
                $( tooltip ).hide();
            }); 
    
    });
};

function takePosition() {
    //first check if you are either controller or turtlebot...
    if (! isMatchingName(tx_gapi_turtlebot_name) && 
        ! isMatchingName(tx_gapi_controller_name) ) return;
    console.log(nav_map_setup);
    switch (nav_map_setup) {
        case ENUM_BOT_START :
            //placeStartDot();
            map_nav_pose_x = coordinatesFromX( coord_x);// - 4);
            map_nav_pose_y = coordinatesFromY( coord_y - 4);
            placeStartDot();
        break;
        
        case ENUM_BOT_END :
            //placeEndDot();
            map_nav_goal_x = coordinatesFromX( coord_x);// - 4);
            map_nav_goal_y = coordinatesFromY( coord_y - 4);
            placeEndDot();
        break;
        
        case ENUM_BOT_NONE :
        
        break;
    }
}

function coordinatesFromX( some_x) {
    return (some_x * map_nav_resolution) + map_nav_origin_x ;
    //return (some_x  + map_nav_origin_x); // * map_nav_resolution;
}

function coordinatesFromY( some_y) {
    return (( $('#mapimg').height() - some_y) * map_nav_resolution) + map_nav_origin_y ;
    //return (( $('#mapimg').height() - some_y) + map_nav_origin_y ); //* map_nav_resolution;
}

function takeAngle() {
    //first check if you are either controller or turtlebot...
    if (! isMatchingName(tx_gapi_turtlebot_name) && 
        ! isMatchingName(tx_gapi_controller_name) ) return;
        
    switch (nav_map_setup) {
        case ENUM_BOT_START :
        break;
        
        case ENUM_BOT_END :
        break;
        
        case ENUM_BOT_NONE :
        break;
    }
}

function chooseStart() {
    nav_map_setup = ENUM_BOT_START;
}

function chooseStop() {
    nav_map_setup = ENUM_BOT_END;
}

function chooseClear() {
    nav_map_setup = ENUM_BOT_NONE;
    //clear vars and img div...
    $('.dot').remove();
    $('#startDot').remove();
    $('.enddot').remove();
    $('#endDot').remove();
    map_nav_pose_x = 0;
    map_nav_pose_y = 0;
    map_nav_pose_a = 0;
    map_nav_goal_x = 0;
    map_nav_goal_y = 0;
    map_nav_goal_a = 0;
    document.getElementById('angleStart').src = anglePng(0);
    document.getElementById('angleStop').src = anglePng(0);
    $('#xyStart').html('xy: ' + map_nav_pose_x.toFixed(2) + ',' + 
        map_nav_pose_y.toFixed(2));
    $('#xyStop').html('xy: ' + map_nav_goal_x.toFixed(2) 
        + ',' + map_nav_goal_y.toFixed(2));
    $('#angleStartDisplay').html(map_nav_pose_a.toFixed(2));
    $('#angleStopDisplay').html(map_nav_goal_a.toFixed(2));
    angle_count_start = 0;
    angle_count_stop = 0;
}

function anglePng(angle) {
    var num = '' ;
    num = '000' + angle;
    var offset = 0;
    if (num.length > 3) offset = 1;
    var nums = num[ num.length - 3] + num[ num.length - 2 ] + num[num.length - 1] ;
    
    return "//awesometelenp.appspot.com/static/bitmap/angle" + nums + ".png"
}

function makeangleStart() {
    angle_count_start += 30;
    angle_count_start = angle_count_start % 360;
    map_nav_pose_a = angle_count_start * (Math.PI /180);
    document.getElementById('angleStart').src = anglePng(angle_count_start);
    $('#angleStartDisplay').html(map_nav_pose_a.toFixed(2));
}

function makeangleStop() {
    angle_count_stop += 30;
    angle_count_stop = angle_count_stop % 360;
    map_nav_goal_a = angle_count_stop * (Math.PI/180);
    document.getElementById('angleStop').src = anglePng(angle_count_stop);
    $('#angleStopDisplay').html(map_nav_goal_a.toFixed(2));
}

function chooseAccept() {

    //check for sanity...
    var reply = confirm("NAV command! " + "\n\n" + 
        "start: " + map_nav_pose_x.toFixed(2) + "," + map_nav_pose_y.toFixed(2) + "\n" +
        "start angle: " + map_nav_pose_a.toFixed(2) + "\n" +
        "stop: " + map_nav_goal_x.toFixed(2) + "," + map_nav_goal_y.toFixed(2) +"\n" +
        "stop angle: " + map_nav_goal_a.toFixed(2) + "\n\n" +
        "originXY: " + map_nav_origin_x.toFixed(2) + "," + map_nav_origin_y.toFixed(2) + "\n" +
        "resolution: "+ map_nav_resolution.toFixed(2) + "\n" +
        "send??!!"
    );
    if (reply == true) {
        sendMapCommands(map_command_nav_execute, 0, '', '', map_command_nav_execute,
            map_nav_pose_x, map_nav_pose_y, map_nav_pose_a,
            map_nav_goal_x, map_nav_goal_y, map_nav_goal_a );
    }
}

function placeStartDot() {
    
    $('.dot').remove();
    $('#startDot').remove();
    var dot = $( '<img id="startDot" ' +
            ' src="//awesometelenp.appspot.com/static/bitmap/pix_blue.png" ' +
            ' class="dot">' ).
        appendTo( '#showMapSpaceDiv' )[0];

        
    //var pos = $('#showMapSpaceView').position();
    $( dot ).css({
        padding: 0 ,
        margin: 0,
        border: 0, 
        left: coord_x - 4,//($(dot).width() ) ,
        top: coord_y - 4  //($(dot).height() ) 
    }).show();
    
    
    
    $('#xyStart').html('xy: ' + map_nav_pose_x.toFixed(2) + ',' + 
        map_nav_pose_y.toFixed(2));
}

function placeEndDot() {
    
    $('.enddot').remove();
    $('#endDot').remove();
    var enddot = $( '<img id="endDot" ' +
            ' src="//awesometelenp.appspot.com/static/bitmap/pix_red.png" ' +
            ' class="enddot">' ).
        appendTo( '#showMapSpaceDiv' )[0];

        
    //var pos = $('#showMapSpaceView').position();
    $( enddot ).css({
        padding: 0 ,
        margin: 0,
        border: 0, 
        left: coord_x - 4,// ($(enddot).width() ) ,
        top: coord_y  - 4 // ($(enddot).height() ) 
    }).show();
    
    
    $('#xyStop').html('xy: ' + map_nav_goal_x.toFixed(2) 
        + ',' + map_nav_goal_y.toFixed(2));
}

function sendInitialPose(x, y, z, a) {
    if (typeof x === 'undefined') x = map_nav_pose_x;
    if (typeof y === 'undefined') y = map_nav_pose_y;
    if (typeof z === 'undefined') z = map_nav_pose_z;
    if (typeof a === 'undefined') a = map_nav_pose_a;
    var initialpose = new ROSLIB.Message({
        header: {
            seq: 0,
            stamp: 0,
            frame_id: "map" //"base_link" // just rviz!!
            },
        pose: {
            pose : {
                position : {
                    x: x,
                    y: y,
                    z: z
                    },
                orientation: {
                    x: 0,
                    y: 0,//Math.sin( a / 2 ), // theta/2 ?
                    z: Math.sin( a / 2 ), // 0,
                    w: Math.cos( a / 2 )  // theta/2 ?
                    }
                },
            covariance : 
                [
                //float64[36]
                0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0
                ]
                
            
            }
    });
    
    map_initialpose.publish(initialpose);
    
}

function sendGoalPose(x,y,z,a) {
    if (typeof x === 'undefined') x = map_nav_goal_x;
    if (typeof y === 'undefined') y = map_nav_goal_y;
    if (typeof z === 'undefined') z = map_nav_goal_z;
    if (typeof a === 'undefined') a = map_nav_goal_a;
    
    console.log("goal -- x,y: " + x + "," + y + " angle: " + a);
    
    
    var simplegoal = new ROSLIB.Message({
        
        header : {
            seq: 0,
            stamp: 0,// {},
            frame_id : "map"
            },
        pose : {
            position: {
                x: x,
                y: y,
                z: z
                },
            orientation: {
                x : 0,
                y : 0,
                z : Math.sin( a / 2 ),
                w : Math.cos( a / 2 ),
                }
            }
    });
    
    var goaltopic = new ROSLIB.Topic({
    	'ros' : ros,
    	'name' : app_manager_prefix + '/move_base_simple/goal',
   		 messageType : 'geometry_msgs/PoseStamped'
    });
    
    goaltopic.publish(simplegoal);
}
</script>


<body style="background-color: #999">
<div style="padding: 0px 0px 0px 0px; background-color: #000">
	<img src="//awesometelenp.appspot.com/static/bitmap/tab_controls.png" 
	alt="CONTROLS" onclick="trySetupControls()" id="tabControls">
	<img src="//awesometelenp.appspot.com/static/bitmap/tab_setup_unselected.png" 
	alt="SETUP" onclick="trySetupText()" id="tabText">
	<img src="//awesometelenp.appspot.com/static/bitmap/tab_map_unselected.png" 
	alt="MAP" onclick="trySetupMap()" id="tabMap">
</div>
<div style="float: left; padding: 0px 20px; background-color: #999"
	id="setupControls">


	<br>
	<table border="0" id="padTable">
	<tr>
	<td></td>
	<td><img src="//awesometelenp.appspot.com/static/bitmap/button_up.png" 
		onmousedown="tryUpClick()" onmouseup="tryClearTimer()" onmouseout="tryClearTimer()" 
		alt="CLICK"></td>
	<td></td>
	</tr>
	<tr>
	<td><img src="//awesometelenp.appspot.com/static/bitmap/button_left.png" 
		onmousedown="tryLeftClick()" onmouseup="tryClearTimer()" onmouseout="tryClearTimer()" 
		alt="CLICK"></td>
	<td id="middleButtonHtml"><img src="//awesometelenp.appspot.com/static/bitmap/button_center.png"  
		onmousedown="tryStopClick()" alt="CLICK" id="middleButtonSrc"></td>
	<td><img src="//awesometelenp.appspot.com/static/bitmap/button_right.png" 
		onmousedown="tryRightClick()" onmouseup="tryClearTimer()" onmouseout="tryClearTimer()" 
		alt="CLICK"></td>
	</tr>
	<tr>
	<td></td>
	<td><img src="//awesometelenp.appspot.com/static/bitmap/button_down.png"  
		onmousedown="tryDownClick()" onmouseup="tryClearTimer()" onmouseout="tryClearTimer()" 
		alt="CLICK"></td>
	<td></td>
	</tr>
	</table>

  <br>
  
<div style="clear: both; background-color:#aaaaaa" id="alertText">
	<b style="color:green;font-size:10pt">[free] </b>
	<b style="color:green;font-size:10pt">[running] </b>
	<b style="color:green;font-size:10pt">[clear]</b>
</div>  
  
<div style="clear: both; background-color:#aaaaaa; display:none" id="controllerText">
	<input type=checkbox value="Controller" id="setController"
        onClick="tryControllerClick()">Controller Node?</input><br>
</div>
  
  <table border="0" id="turtlebotTable">
  <tr><td>
	<b>Start:</b><br>
  <input type=checkbox value="Turtlebot" id="setTurtlebot"
        onClick="tryTurtlebotClick()">Turtlebot Node?</input><br>
       
	</td></tr><tr><td>
	<b>Message Type:</b><br>
	<form action="">
	<input type="radio" name="message" id="messageString" 
	value="string" onclick="tryRadioClick()" >String<br>
	
	<input type="radio" name="message" id="messageTwist" 
	value="cmdvel" onclick="tryRadioClick()">Twist<br>
	
	<input type="radio" name="message" id="messageStamped" 
	value="velocity" onclick="tryRadioClick()">TwistStamped
	</form>
	</td></tr>
	</table>
<br>
</div>

<div style="clear: both; background-color:#aaaaaa; display: none;" id="monitorDiv">
	<br>
	TURTLEBOT MONITOR:
</div>

<div style="clear: both; background-color:#aaaaaa; display: none;" id="setupText">
	<br>
	TURTLEBOT SETUP:
</div>
<!-- /body tag is now after 'app-map.html' code -->
<!-- one div for entire tab -->

<style>
table
{
    border-collapse:collapse;
}
table, td, tr
{
    border:0px solid black;
}
table.lined, td.lined, tr.lined
{
    border-collapse:separate;
    border:1px solid black;
}
img
{
    vertical-align:middle;
}
button
{
    padding:0;
    margin:0;
}
#tooltip 
{
    font-size:10px;
    position: absolute;
    top: 0px;
    right:0px;
    width:100px;
    visibility: visible;
    color:black;
    background-color:#ffffff;
    border: 1px solid #66ccff;
    z-index: 10;
    padding:4px;
}
img.dot, img.enddot
{
    position: absolute;
    top: 0px;
    left:0px;
    visibility: visible;
    z-index: 8;
    padding:0px;
}
#showMapSpaceDiv
{
    position: relative;
    
}
#showMapSpaceView
{
    position: relative;
    
}
p.reply
{
    padding: 15px;
    border: 10px solid yellow;
    
}
</style>

<div style="clear: both; background-color:#aaaaaa; display: none;" id="setupMap">
<div id="topstatus"></div>

<!-- one div for each frame of wizard  CHOOSE-->
<div style="clear: both; background-color:#aaaaaa; display: block;" id="wizChooseOp">

    <br>
<table border=0 id="wizChooseOpTable" style="width:100%">
<tr><td>Do This:<br></td></tr><!-- Make Test Map -->
<tr><td><button type="button"  id="opMake" onclick="opMake()" style="width:100%">Make Test Map</button></td></tr>
<tr><td><button type="button"  id="opSave" onclick="opSave()" style="width:100%" disabled>Save Map</button></td></tr>
<!-- tr><td><button type="button"  id="opChoose" onclick="opChoose()" style="width:100%" disabled>List Maps</button></td></tr -->
<tr><td>Or Do This:<br></td></tr><!-- Map Manage -->
<tr><td><button type="button"  id="opLoad" onclick="opLoad()" style="width:100%">Load Map</button></td></tr>
<tr><td>Sometimes Do This:<br></td></tr><!-- View Map, Etc... -->
<tr><td><button type="button"  id="opStart" onclick="opStart()" style="width:100%">Manage Maps</button></td></tr>
<tr><td><button type="button"  id="opDelete" onclick="opDelete()" style="width:100%">Delete Map</button></td></tr>
<tr><td><button type="button"  id="opRename" onclick="opRename()" style="width:100%">Rename Map</button></td></tr>
<tr><td><button type="button"  id="opList" onclick="opList()" style="width:100%">List Maps</button></td></tr>
<tr><td><button type="button"  id="opView" onclick="opView()" style="width:100%">View Current Map</button></td></tr>
<tr><td><button type="button"  id="stopService" onclick="opStopService()" style="width:100%">STOP/SWITCH SERVICE</button></td></tr>
</table>
<br>

</div><!-- end of table -->

<!-- one div for each frame of wizard  LIST -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpList">
    <button type="button" onclick="executeList()">Refresh</button>
    List of Maps:<br>
    <div id="listSpace" style="border-style:solid;border-width:3px; border-color:black;
        width:300px; height:175px; overflow:auto">
    Click 'LIST' button to see... <br>
    
    </div><br>
    <div class="listLength"></div>
<br>

<button type="button" onclick="opCancel()">Return</button>

    
<br>

</div>

<!-- one div for each frame of wizard  LOAD -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpLoad">
    Loading a file automatically starts the map navigating software. 
    Then click 'RUN-NAV-TOOLS' to set start and stop coordinates.<br><br>
    IF the load option pull-down does not contain any maps, click the Force-Library 
    or Reload-List button.
    <button type="button" onclick='executeLibraryForce()'>FORCE LIBRARY</button>
    <button type="button" onclick='opLoad()'>RELOAD LIST</button><br>
    <hr>
    Load this file:
    <!-- form action="" -->
    <select id="selectSpaceLoad">
    <option value="none">None</option>
    </select><button type="button" onclick="executeLoad()">LOAD</button>
    <div class="listLength"></div>
    <!-- /form -->
<br>
<button type="button" onclick="executeRunNav()">RUN NAV TOOLS</button>
<button type="button" onclick='executeRunNavForce();'>FORCE NAV MANAGER</button><br>

<button type="button" onclick="opCancel()">Done</button>
<p id="wizOpLoadConfirm" style="display:none" class="reply">Your map loaded.</p>
<p id="wizOpLoadNavConfirm" style="display:none" class="reply">Nav functions have been started.</p>
    
</div>

<!-- one div for each frame of wizard  NEW -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpNew">
    <br>
    Make a test map here. This map will allow you to test saving and loading 
    functions.<br>
    <button type="button" onclick="executeNew()">NEW TEST MAP</button><br>
    <br>
    Start map app that will make and save one map. Map should be usable for
    actual gmapping.<br>
    <button type="button" onclick="executeMakeMapAndroid()">NEW G MAP</button><br><br>
<button type="button" onclick="opCancel()">Done</button>
<p id="wizOpNewConfirm" style="display:none" class="reply">New map ready.</p>
</div>
<!-- one div for each frame of wizard  DELETE -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpDel">
    <br>
    Delete this file:
    <!-- form action="" -->
    <select id="selectSpaceDelete">
    <option value="none">None</option>
    </select><button type="button" onclick="executeDelete()">DELETE</button><br>
    <!-- /form -->
<button type="button" onclick="opCancel()">Done</button>
    <p id="wizOpDelConfirm" style="display:none" class="reply">
    Your map was deleted. Refresh or click 'Close' to see new
    list: <div class="listLength"></div></p>
</div>
<!-- one div for each frame of wizard  RENAME -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpRename">
    Rename this file:
    <br>
    <!-- form action="" -->
    <button type="button" onclick='opRename()'>REFRESH</button><br>
    <select id="selectSpaceRename">
    <option value="none">None</option>
    </select>
    <input type="text" name="rename" id="inputSpaceRename">
    <button type="button" onclick="executeRename()">RENAME</button><br>
    <!-- /form -->
<button type="button" onclick="opCancel()">Done</button>
    <p id="wizOpRenameConfirm" style="display:none" class="reply">
    Your map was renamed. Refresh of click 'Done' to see new
    list</p>
</div>
<!-- one div for each frame of wizard  SAVE -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpSave">
    <br>
    If you want to save a map, make the map
    first with the 'G-MAP' option under 'Make-Map'.
    <hr>
    <br>
    Give your map a name:
    <input type="text" name="rename" id="inputSpaceSave">
    <button type="button" onclick="executeSave()">SAVE</button><br>
<button type="button" onclick="opCancel()">Done</button>
<p id="wizOpSaveConfirm" style="display:none" class="reply">Your map was saved.</p>
</div>
<!-- one div for each frame of wizard  DONE -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpDone">
<button type="button" onclick="">Done</button>
<p id="wizOpDoneConfirm" style="display:none">Your operation is done.</p>
</div>
<!-- one div for each frame of wizard  START ROBOT / CONFIG-->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpStart">
    
<br>
<button type="button" onclick='executeMapStart();'>FORCE MAP CLEAN</button><br><br>
    
<button type="button" onclick="opCancel()">Done</button><br>
<p id="wizOpStartConfirm" style="display:none" class="reply">The map manager is started.</p>
    
<p id="wizOpStartConfirmForce" style="display:none" class="reply">The map manager is cleaning.</p>
    
</div>
<!-- one div for each frame of wizard  VIEW MAP -->
<div style="clear: both; background-color:#aaaaaa; display: none;" id="wizOpView">
    <button type="button" onclick='getMapTopicView();'>Refresh Current Map</button>
    <div id="showMapSpaceView" style="border-style:solid;border-width:1px; border-color:black;
        width:300px; height:175px; overflow:auto; font-size:3px; padding:0px 0px 0px 0px;"><div 
        style="font-size:12pt;" id="showMapSpaceDiv"></div></div>


<br>
<!-- start of complicated nav div -->
    <div id="wizOpNavSettings" style="display:none">
    <table class="lined"><tr class="lined">
        <td class="lined"><!-- start location stuff -->
            <button type="button" onclick="chooseStart()">START COORDS</button>
        </td>
        <td class="lined"><!-- stop location stuff -->
            <button type="button" onclick="chooseStop()">STOP COORDS</button>
        </td>
    </tr>
    <tr class="lined">
        <td class="lined" valign="top"><!-- start location stuff -->
            click here for angle at start position <br>
            <img id="angleStart" onclick='makeangleStart()' src="//awesometelenp.appspot.com/static/bitmap/angle000.png">
            <br>
            <div id="xyStart"></div><br>
            Angle: <div id="angleStartDisplay">0</div>
        </td>
        <td class="lined" valign="top"><!-- stop location stuff -->
            click here for angle desired at end position <br>
            <img id="angleStop" onclick='makeangleStop()' src="//awesometelenp.appspot.com/static/bitmap/angle000.png">
            <br>
            <div id="xyStop"></div><br>
            Angle: <div id="angleStopDisplay">0</div>
        </td>
    </tr>
    <tr class="lined"><td class="lined" colspan="2">
    <button type="button" onclick="chooseClear()">NO COORDS</button>
    <button type="button" onclick="chooseAccept()">SEND ALL !</button>
    </td></tr>
    <tr class="lined"><td class="lined" colspan="2">
    <button type="button" onclick="executeNavStart()">SEND START</button>
    <button type="button" onclick="executeNavGoal()">SEND GOAL</button>
    </td></tr>
    </table>
    
    </div>
    
    
<!-- end of complicated nav div -->
<br>
<button type="button" onclick="opCancel()">Done</button>
<p id="wizOpViewConfirm" style="display:none" class="reply">Your map is shown.</p>
</div>
<!-- end of wizard -->
</div>
<!-- closing body tag -->
</body>
